Hibernate 5 Support

This commit is contained in:
Jan-Willem Gmelig Meyling 2020-05-31 18:49:09 +02:00
parent b9363a4433
commit 8cd82e8792
8 changed files with 106 additions and 31 deletions

View File

@ -28,8 +28,9 @@ import com.querydsl.core.types.Ops;
* HQLTemplates extends {@link JPQLTemplates} with Hibernate specific extensions
*
* @author tiwe
*
* @deprecated Most likely you want to use {@link Hibernate5Templates} instead
*/
@Deprecated
public class HQLTemplates extends JPQLTemplates {
private static final QueryHandler QUERY_HANDLER;
@ -86,16 +87,22 @@ public class HQLTemplates extends JPQLTemplates {
@Override
public boolean wrapElements(Operator operator) {
// For example: JPaIntegration.docoExamples98_12
return wrapElements.contains(operator);
}
@Override
public String getTypeForCast(Class<?> cl) {
return typeNames.get(cl);
String typeName = typeNames.get(cl);
if (typeName == null) {
return super.getTypeForCast(cl);
}
return typeName;
}
@Override
public String getExistsProjection() {
// TODO Required / supported just for Hibernate?
return "1";
}

View File

@ -0,0 +1,32 @@
package com.querydsl.jpa;
/**
* Hibernate5Templates extends {@link JPQLTemplates} with Hibernate specific extensions
*
* @author Jan-Willem Gmelig Meyling
*
*/
public class Hibernate5Templates extends HQLTemplates {
public static final Hibernate5Templates DEFAULT = new Hibernate5Templates();
public Hibernate5Templates() {
}
public Hibernate5Templates(char escape) {
super(escape);
}
@Override
public boolean wrapConstant(Object constant) {
// HHH-6913 is fixed in 5.0, default to JPA behaviour
return false;
}
@Override
public boolean isWithForOn() {
// Hibernate supports the on-clause since 5.0, and the ON clause is actually mandatory for entity joins
return true;
}
}

View File

@ -15,6 +15,7 @@ package com.querydsl.jpa;
import java.util.Iterator;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import org.hibernate.ScrollMode;
@ -32,7 +33,7 @@ import com.querydsl.core.types.FactoryExpression;
* @author tiwe
*
*/
class HibernateHandler implements QueryHandler {
public class HibernateHandler implements QueryHandler {
@Override
public void addEntity(Query query, String alias, Class<?> type) {
@ -52,15 +53,15 @@ class HibernateHandler implements QueryHandler {
@SuppressWarnings("unchecked")
@Override
public <T> CloseableIterator<T> iterate(Query query, FactoryExpression<?> projection) {
if (query instanceof NativeQuery) {
NativeQuery hQuery = (NativeQuery) query;
ScrollableResults results = hQuery.scroll(ScrollMode.FORWARD_ONLY);
try {
org.hibernate.query.Query unwrappedQuery = query.unwrap(org.hibernate.query.Query.class);
ScrollableResults results = unwrappedQuery.scroll(ScrollMode.FORWARD_ONLY);
CloseableIterator<T> iterator = new ScrollableResultsIterator<T>(results);
if (projection != null) {
iterator = new TransformingIterator<T>(iterator, projection);
}
return iterator;
} else {
} catch (PersistenceException e) {
Iterator<T> iterator = query.getResultList().iterator();
if (projection != null) {
return new TransformingIterator<T>(iterator, projection);
@ -73,11 +74,11 @@ class HibernateHandler implements QueryHandler {
@SuppressWarnings("deprecation")
@Override
public boolean transform(Query query, FactoryExpression<?> projection) {
if (query instanceof NativeQuery) {
try {
ResultTransformer transformer = new FactoryExpressionTransformer(projection);
query.unwrap(NativeQuery.class).setResultTransformer(transformer);
query.unwrap(org.hibernate.query.Query.class).setResultTransformer(transformer);
return true;
} else {
} catch (PersistenceException e) {
return false;
}
}

View File

@ -18,7 +18,13 @@ import java.util.Map;
import javax.persistence.EntityManager;
import com.google.common.collect.Maps;
import com.querydsl.jpa.*;
import com.querydsl.jpa.BatooTemplates;
import com.querydsl.jpa.DataNucleusTemplates;
import com.querydsl.jpa.EclipseLinkTemplates;
import com.querydsl.jpa.HQLTemplates;
import com.querydsl.jpa.Hibernate5Templates;
import com.querydsl.jpa.JPQLTemplates;
import com.querydsl.jpa.OpenJPATemplates;
/**
* {@code JPAProvider} provides detection of the JPA provider based on the EntityManager instance
@ -39,9 +45,23 @@ public final class JPAProvider {
}
static {
boolean hibernate5;
try {
String version = Class.forName("org.hibernate.Session").getPackage().getImplementationVersion();
String[] versionParts = version.split("\\.");
int major = Integer.parseInt(versionParts[0]);
hibernate5 = major >= 5;
} catch (ClassNotFoundException e) {
hibernate5 = false;
}
JPQLTemplates hibernateTemplates = hibernate5 ? Hibernate5Templates.DEFAULT : HQLTemplates.DEFAULT;
addMapping("org.batoo.jpa.core.impl.manager.EntityManagerImpl", BatooTemplates.DEFAULT);
addMapping("org.hibernate.Session", HQLTemplates.DEFAULT);
addMapping("org.hibernate.ejb.HibernateEntityManager", HQLTemplates.DEFAULT);
addMapping("org.hibernate.Session", hibernateTemplates);
addMapping("org.hibernate.ejb.HibernateEntityManager", hibernateTemplates);
addMapping("org.hibernate.jpa.HibernateEntityManager", hibernateTemplates);
addMapping("org.eclipse.persistence.jpa.JpaEntityManager", EclipseLinkTemplates.DEFAULT);
addMapping("org.apache.openjpa.persistence.OpenJPAEntityManager", OpenJPATemplates.DEFAULT);
addMapping("org.datanucleus.jpa.EntityManagerImpl", DataNucleusTemplates.DEFAULT);
@ -51,15 +71,23 @@ public final class JPAProvider {
templatesByName.put("batoo", BatooTemplates.DEFAULT);
templatesByName.put("eclipselink", EclipseLinkTemplates.DEFAULT);
templatesByName.put("hibernate", HQLTemplates.DEFAULT);
templatesByName.put("hibernate5", Hibernate5Templates.DEFAULT);
templatesByName.put("openjpa", OpenJPATemplates.DEFAULT);
templatesByName.put("datanucleus", DataNucleusTemplates.DEFAULT);
}
public static JPQLTemplates getTemplates(EntityManager em) {
// detect by delegate
for (Map.Entry<Class<?>, JPQLTemplates> entry : mappings.entrySet()) {
if (entry.getKey().isAssignableFrom(em.getDelegate().getClass())) {
return entry.getValue();
Class<?> entityManagerClass = entry.getKey();
try {
if (entityManagerClass.isInstance(em.unwrap(entityManagerClass))) {
return entry.getValue();
}
} catch (Exception e) { // The PersistenceException is wrapped in an InvocationException for EclipseLink
// detect by delegate
if (entityManagerClass.isAssignableFrom(em.getDelegate().getClass())) {
return entry.getValue();
}
}
}
// detect by properties

View File

@ -22,9 +22,11 @@ import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.instanceOf;
import static org.hibernate.ScrollMode.FORWARD_ONLY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class HibernateHandlerTest {
@ -97,10 +99,11 @@ public class HibernateHandlerTest {
ScrollableResultsImplementor scrollableResultsImplementor = createMock(ScrollableResultsImplementor.class);
FactoryExpression<?> factoryExpression = createMock(FactoryExpression.class);
expect(nativeQuery.unwrap(NativeQuery.class)).andReturn(nativeQuery);
expect(nativeQuery.unwrap(org.hibernate.query.Query.class)).andReturn(nativeQuery);
expect(nativeQuery.scroll(FORWARD_ONLY)).andReturn(scrollableResultsImplementor);
replay(nativeQuery);
assertEquals(TransformingIterator.class, hibernateHandler.iterate(nativeQuery, factoryExpression).getClass());
assertThat(hibernateHandler.iterate(nativeQuery, factoryExpression), instanceOf(TransformingIterator.class));
}
@Test
@ -109,6 +112,7 @@ public class HibernateHandlerTest {
List queryResultList = createMock(List.class);
Iterator iterator = createMock(Iterator.class);
expect(query.unwrap(org.hibernate.query.Query.class)).andThrow(new PersistenceException("Cannot unwrap Query"));
expect(query.getResultList()).andReturn(queryResultList);
expect(queryResultList.iterator()).andReturn(iterator);
replay(query);
@ -123,6 +127,7 @@ public class HibernateHandlerTest {
List queryResultList = createMock(List.class);
Iterator iterator = createMock(Iterator.class);
expect(query.unwrap(org.hibernate.query.Query.class)).andThrow(new PersistenceException("Cannot unwrap Query"));
expect(query.getResultList()).andReturn(queryResultList);
expect(queryResultList.iterator()).andReturn(iterator);
replay(query);
@ -134,7 +139,7 @@ public class HibernateHandlerTest {
public void should_transform() {
FactoryExpression<?> projection = createMock(FactoryExpression.class);
expect(nativeQuery.unwrap(NativeQuery.class)).andReturn(nativeQuery);
expect(nativeQuery.unwrap(org.hibernate.query.Query.class)).andReturn(nativeQuery);
expect(nativeQuery.setResultTransformer(anyObject(ResultTransformer.class))).andReturn(nativeQuery);
replay(nativeQuery);

View File

@ -29,6 +29,7 @@ import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import com.querydsl.core.Tuple;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Rule;
@ -252,10 +253,10 @@ public class JPABase extends AbstractJPATest implements JPATest {
@NoEclipseLink
@NoBatooJPA
public void createQuery() {
List<Object[]> rows = query().from(cat)
List<Tuple> rows = query().from(cat)
.select(cat.id, cat.name).createQuery().getResultList();
for (Object[] row : rows) {
assertEquals(2, row.length);
for (Tuple row : rows) {
assertEquals(2, row.size());
}
}
@ -264,10 +265,10 @@ public class JPABase extends AbstractJPATest implements JPATest {
@NoEclipseLink
@NoBatooJPA
public void createQuery2() {
List<Object[]> rows = query().from(cat)
List<Tuple> rows = query().from(cat)
.select(cat.id, cat.name).createQuery().getResultList();
for (Object[] row : rows) {
assertEquals(2, row.length);
for (Tuple row : rows) {
assertEquals(2, row.size());
}
}

View File

@ -38,7 +38,7 @@ public class JPAProviderTest {
factory = Persistence.createEntityManagerFactory("h2");
em = factory.createEntityManager();
System.out.println(em.getDelegate().getClass());
assertEquals(HQLTemplates.DEFAULT, JPAProvider.getTemplates(em));
assertEquals(Hibernate5Templates.DEFAULT, JPAProvider.getTemplates(em));
}
@Test
@ -55,7 +55,7 @@ public class JPAProviderTest {
Thread.currentThread().getContextClassLoader(),
new Class<?>[]{EntityManager.class},
handler);
assertEquals(HQLTemplates.DEFAULT, JPAProvider.getTemplates(proxy));
assertEquals(Hibernate5Templates.DEFAULT, JPAProvider.getTemplates(proxy));
}
@Test

View File

@ -76,7 +76,8 @@ public class JPAQueryFactoryTest {
public void query3() {
EasyMock.expect(mock.getEntityManagerFactory()).andReturn(factoryMock);
EasyMock.expect(factoryMock.getProperties()).andReturn(properties);
EasyMock.expect(mock.getDelegate()).andReturn(mock).atLeastOnce();
EasyMock.expect(mock.unwrap(EasyMock.anyObject(Class.class))).andReturn(mock).atLeastOnce();
EasyMock.replay(mock, factoryMock);
queryFactory3.query().from(QAnimal.animal);
@ -104,7 +105,7 @@ public class JPAQueryFactoryTest {
public void delete3() {
EasyMock.expect(mock.getEntityManagerFactory()).andReturn(factoryMock);
EasyMock.expect(factoryMock.getProperties()).andReturn(properties);
EasyMock.expect(mock.getDelegate()).andReturn(mock).atLeastOnce();
EasyMock.expect(mock.unwrap(EasyMock.anyObject(Class.class))).andReturn(mock).atLeastOnce();
EasyMock.replay(mock, factoryMock);
assertNotNull(queryFactory3.delete(QAnimal.animal));
@ -128,7 +129,7 @@ public class JPAQueryFactoryTest {
public void update3() {
EasyMock.expect(mock.getEntityManagerFactory()).andReturn(factoryMock);
EasyMock.expect(factoryMock.getProperties()).andReturn(properties);
EasyMock.expect(mock.getDelegate()).andReturn(mock).atLeastOnce();
EasyMock.expect(mock.unwrap(EasyMock.anyObject(Class.class))).andReturn(mock).atLeastOnce();
EasyMock.replay(mock, factoryMock);
assertNotNull(queryFactory3.update(QAnimal.animal));
@ -151,7 +152,7 @@ public class JPAQueryFactoryTest {
public void insert3() {
EasyMock.expect(mock.getEntityManagerFactory()).andReturn(factoryMock);
EasyMock.expect(factoryMock.getProperties()).andReturn(properties);
EasyMock.expect(mock.getDelegate()).andReturn(mock).atLeastOnce();
EasyMock.expect(mock.unwrap(EasyMock.anyObject(Class.class))).andReturn(mock).atLeastOnce();
EasyMock.replay(mock, factoryMock);
assertNotNull(queryFactory3.insert(QAnimal.animal));