Fix issue with fetch for hql query

This commit is contained in:
Andrea Boriero 2020-11-26 17:30:34 +01:00
parent c4673e5a5c
commit f54105cc51
8 changed files with 362 additions and 319 deletions

View File

@ -18,17 +18,12 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
* @author Steve Ebersole
*/
public class FromClauseAccessImpl implements FromClauseAccess {
private List<TableGroup> rootTableGroups;
private Map<String, TableGroup> tableGroupBySqlAlias;
private Map<NavigablePath, TableGroup> tableGroupByPath;
public FromClauseAccessImpl() {
}
public List<TableGroup> getRootTableGroups() {
return rootTableGroups;
}
public TableGroup getByAlias(String alias) {
final TableGroup byAlias = findByAlias( alias );
if ( byAlias == null ) {
@ -45,10 +40,6 @@ public class FromClauseAccessImpl implements FromClauseAccess {
}
}
if ( rootTableGroups != null && rootTableGroups.size() == 1 ) {
return rootTableGroups.get( 0 );
}
return null;
}
@ -61,10 +52,6 @@ public class FromClauseAccessImpl implements FromClauseAccess {
}
}
if ( rootTableGroups != null && rootTableGroups.size() == 1 ) {
return rootTableGroups.get( 0 );
}
return null;
}

View File

@ -8,6 +8,7 @@ package org.hibernate.query.sqm.sql;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
@ -249,6 +250,7 @@ public abstract class BaseSqmToSqlAstConverter
private final QueryParameterBindings domainParameterBindings;
private final Map<JpaCriteriaParameter<?>,Supplier<SqmJpaCriteriaParameterWrapper<?>>> jpaCriteriaParamResolutions;
private Map<String,NavigablePath> pluralPersisterElementNavigablePathByFullPath = new HashMap<>();
private final SqlAliasBaseManager sqlAliasBaseManager = new SqlAliasBaseManager();
@ -673,10 +675,12 @@ public abstract class BaseSqmToSqlAstConverter
if ( log.isTraceEnabled() ) {
log.tracef( "Visiting explicit joins for `%s`", sqmFrom.getNavigablePath() );
}
sqmFrom.visitSqmJoins(
sqmJoin -> consumeExplicitJoin( sqmJoin, lhsTableGroup )
sqmJoin -> {
consumeExplicitJoin( sqmJoin, lhsTableGroup );
}
);
pluralPersisterElementNavigablePathByFullPath.clear();
}
@SuppressWarnings("WeakerAccess")
@ -702,6 +706,8 @@ public abstract class BaseSqmToSqlAstConverter
final TableGroupJoin joinedTableGroupJoin;
final TableGroup joinedTableGroup;
final NavigablePath sqmJoinNavigablePath = sqmJoin.getNavigablePath();
final NavigablePath parentNavigablePath = sqmJoinNavigablePath.getParent();
if ( pathSource instanceof PluralPersistentAttribute ) {
final ModelPart pluralPart = lhsTableGroup.getModelPart().findSubPart(
sqmJoin.getReferencedPathSource().getPathName(),
@ -712,7 +718,22 @@ public abstract class BaseSqmToSqlAstConverter
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) pluralPart;
final NavigablePath elementPath = sqmJoin.getNavigablePath().append( CollectionPart.Nature.ELEMENT.getName() );
NavigablePath elementPath;
if ( parentNavigablePath == null ) {
elementPath = sqmJoinNavigablePath.append( CollectionPart.Nature.ELEMENT.getName() );
pluralPersisterElementNavigablePathByFullPath.put( sqmJoin.getNavigablePath().getFullPath(), elementPath );
}
else {
final NavigablePath elementNavigablePath = pluralPersisterElementNavigablePathByFullPath.get( parentNavigablePath.getFullPath() );
if ( elementNavigablePath == null ) {
elementPath = sqmJoinNavigablePath.append( CollectionPart.Nature.ELEMENT.getName() );
pluralPersisterElementNavigablePathByFullPath.put( sqmJoin.getNavigablePath().getFullPath(), elementPath );
}
else {
elementPath = elementNavigablePath.append( pluralAttributeMapping.getPartName() );
pluralPersisterElementNavigablePathByFullPath.put( sqmJoin.getNavigablePath().getFullPath(), elementPath.append( CollectionPart.Nature.ELEMENT.getName() ) );
}
}
joinedTableGroupJoin = pluralAttributeMapping.createTableGroupJoin(
elementPath,
@ -726,7 +747,7 @@ public abstract class BaseSqmToSqlAstConverter
lhsTableGroup.addTableGroupJoin( joinedTableGroupJoin );
fromClauseIndex.register( sqmJoin, joinedTableGroup );
fromClauseIndex.register( sqmJoin, joinedTableGroup, elementPath );
fromClauseIndex.registerTableGroup( elementPath, joinedTableGroup );
}
else if ( pathSource instanceof EmbeddedSqmPathSource ) {
@ -740,10 +761,10 @@ public abstract class BaseSqmToSqlAstConverter
final NavigablePath joinedPath;
final String explicitAlias = sqmJoin.getExplicitAlias();
if ( explicitAlias == null ) {
joinedPath = sqmJoin.getNavigablePath();
joinedPath = sqmJoinNavigablePath;
}
else {
joinedPath = sqmJoin.getNavigablePath().getParent().append( sqmJoin.getAttribute().getName() );
joinedPath = parentNavigablePath.append( sqmJoin.getAttribute().getName() );
}
joinedTableGroupJoin = ( (TableGroupJoinProducer) joinedPart ).createTableGroupJoin(
joinedPath,
@ -780,10 +801,10 @@ public abstract class BaseSqmToSqlAstConverter
final NavigablePath joinedPath;
final String explicitAlias = sqmJoin.getExplicitAlias();
if ( explicitAlias == null ) {
joinedPath = sqmJoin.getNavigablePath();
joinedPath = sqmJoinNavigablePath;
}
else {
joinedPath = sqmJoin.getNavigablePath().getParent().append( sqmJoin.getAttribute().getName() );
joinedPath = parentNavigablePath.append( sqmJoin.getAttribute().getName() );
}
joinedTableGroupJoin = ( (TableGroupJoinProducer) joinedPart ).createTableGroupJoin(
@ -806,7 +827,7 @@ public abstract class BaseSqmToSqlAstConverter
// add any additional join restrictions
if ( sqmJoin.getJoinPredicate() != null ) {
if ( sqmJoin.isFetched() ) {
QueryLogging.QUERY_MESSAGE_LOGGER.debugf( "Join fetch [" + sqmJoin.getNavigablePath() + "] is restricted" );
QueryLogging.QUERY_MESSAGE_LOGGER.debugf( "Join fetch [" + sqmJoinNavigablePath + "] is restricted" );
}
if ( joinedTableGroupJoin == null ) {

View File

@ -38,6 +38,10 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
}
public void register(SqmPath<?> sqmPath, TableGroup tableGroup) {
register( sqmPath, tableGroup, null );
}
public void register(SqmPath<?> sqmPath, TableGroup tableGroup, NavigablePath identifierForTableGroup) {
registerTableGroup( sqmPath.getNavigablePath(), tableGroup );
if ( sqmPath.getExplicitAlias() != null ) {
@ -54,17 +58,20 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
if ( sqmPath instanceof SqmAttributeJoin ) {
final SqmAttributeJoin sqmJoin = (SqmAttributeJoin) sqmPath;
if ( sqmJoin.isFetched() ) {
registerJoinFetch( sqmJoin );
registerJoinFetch( sqmJoin, identifierForTableGroup );
}
}
}
private void registerJoinFetch(SqmAttributeJoin sqmJoin) {
private void registerJoinFetch(SqmAttributeJoin sqmJoin, NavigablePath identifierForTableGroup) {
if ( fetchesByPath == null ) {
fetchesByPath = new HashMap<>();
}
NavigablePath navigablePath = sqmJoin.getNavigablePath();
fetchesByPath.put( navigablePath.getIdentifierForTableGroup(), sqmJoin );
if ( identifierForTableGroup != null ) {
fetchesByPath.put( identifierForTableGroup.getIdentifierForTableGroup(), sqmJoin );
}
}
public boolean isResolved(SqmFrom fromElement) {

View File

@ -31,6 +31,12 @@ public class SimpleFromClauseAccessImpl implements FromClauseAccess {
@Override
public void registerTableGroup(NavigablePath navigablePath, TableGroup tableGroup) {
SqlTreeCreationLogger.LOGGER.debugf(
"Registration of TableGroup [%s] with identifierForTableGroup [%s] for NavigablePath [%s] ",
tableGroup,
tableGroup.getNavigablePath().getIdentifierForTableGroup(),
navigablePath.getIdentifierForTableGroup()
);
final TableGroup previous = tableGroupMap.put( navigablePath.getIdentifierForTableGroup(), tableGroup );
if ( previous != null ) {
SqlTreeCreationLogger.LOGGER.debugf(

View File

@ -78,13 +78,13 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
return;
}
if ( CollectionLoadingLogger.TRACE_ENABLED ) {
CollectionLoadingLogger.INSTANCE.tracef(
"(%s) Beginning Initializer#resolveInstance for collection : %s",
getSimpleConcreteImplName(),
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() )
);
}
// if ( CollectionLoadingLogger.TRACE_ENABLED ) {
// CollectionLoadingLogger.INSTANCE.tracef(
// "(%s) Beginning Initializer#resolveInstance for collection : %s",
// getSimpleConcreteImplName(),
// LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() )
// );
// }
// determine the PersistentCollection instance to use and whether
// we (this initializer) is responsible for loading its state
@ -195,14 +195,14 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
session
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Created new collection wrapper [%s] : %s",
getSimpleConcreteImplName(),
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
toLoggableString( collectionInstance )
);
}
// if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
// CollectionLoadingLogger.INSTANCE.debugf(
// "(%s) Created new collection wrapper [%s] : %s",
// getSimpleConcreteImplName(),
// LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
// toLoggableString( collectionInstance )
// );
// }
persistenceContext.addUninitializedCollection( collectionDescriptor, collectionInstance, collectionKey.getKey() );
@ -210,14 +210,14 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
}
if ( responsibility != null ) {
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Responsible for loading collection [%s] : %s",
getSimpleConcreteImplName(),
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
toLoggableString( collectionInstance )
);
}
// if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
// CollectionLoadingLogger.INSTANCE.debugf(
// "(%s) Responsible for loading collection [%s] : %s",
// getSimpleConcreteImplName(),
// LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
// toLoggableString( collectionInstance )
// );
// }
if ( getParentAccess() != null ) {
getParentAccess().registerResolutionListener(
@ -287,28 +287,12 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
collectionAttributeMapping.getCollectionDescriptor(),
keyContainerValue
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Current row collection key : %s",
getSimpleConcreteImplName(),
LoggingHelper.toLoggableString( getNavigablePath(), this.collectionKey.getKey() )
);
}
}
else if ( keyCollectionValue != null ) {
this.collectionKey = new CollectionKey(
collectionAttributeMapping.getCollectionDescriptor(),
keyCollectionValue
);
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Current row collection key : %s",
getSimpleConcreteImplName(),
LoggingHelper.toLoggableString( getNavigablePath(), this.collectionKey.getKey() )
);
}
}
else {
this.collectionKey = new CollectionKey(
@ -351,14 +335,14 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol
if ( collectionValueKey != null ) {
// the row contains an element in the collection...
if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
CollectionLoadingLogger.INSTANCE.debugf(
"(%s) Reading element from row for collection [%s] -> %s",
getSimpleConcreteImplName(),
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
toLoggableString( collectionInstance )
);
}
// if ( CollectionLoadingLogger.DEBUG_ENABLED ) {
// CollectionLoadingLogger.INSTANCE.debugf(
// "(%s) Reading element from row for collection [%s] -> %s",
// getSimpleConcreteImplName(),
// LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
// toLoggableString( collectionInstance )
// );
// }
responsibility.load(
loadingState -> readCollectionRow( collectionKey, loadingState, rowProcessingState )

View File

@ -40,6 +40,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
private final Object[] resolvedValues;
private final boolean createEmptyCompositesEnabled;
private Object compositeInstance;
private boolean keyResolved;
private boolean instanceResolved;
@SuppressWarnings("WeakerAccess")
@ -93,6 +95,9 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if(keyResolved){
return;
}
final PropertyAccess parentInjectionPropertyAccess = embeddedModelPartDescriptor.getParentInjectionAttributePropertyAccess();
final FetchParentAccess fetchParentAccess = getFetchParentAccess();
@ -113,14 +118,19 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
}
);
}
keyResolved = true;
}
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( instanceResolved ) {
return;
}
compositeInstance = embeddedModelPartDescriptor.getEmbeddableTypeDescriptor()
.getRepresentationStrategy()
.getInstantiator()
.instantiate( rowProcessingState.getSession().getFactory() );
instanceResolved = true;
EmbeddableLoadingLogger.INSTANCE.debugf(
"Created composite instance [%s] : %s",
navigablePath,
@ -192,7 +202,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
@Override
public void finishUpRow(RowProcessingState rowProcessingState) {
compositeInstance = null;
keyResolved = true;
instanceResolved = false;
clearParentResolutionListeners();
}

View File

@ -30,6 +30,8 @@ public class EmbeddableAssembler implements DomainResultAssembler {
@Override
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
initializer.resolveKey( rowProcessingState );
initializer.resolveInstance( rowProcessingState );
return initializer.getCompositeInstance();
}

View File

@ -6,275 +6,300 @@
*/
package org.hibernate.test.cid;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.persistence.PersistenceException;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.exception.SQLGrammarException;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
*/
public class CompositeIdTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "cid/Customer.hbm.xml", "cid/Order.hbm.xml", "cid/LineItem.hbm.xml", "cid/Product.hbm.xml" };
}
@Test
public void testQuery() {
Session s = openSession();
Transaction t = s.beginTransaction();
s.createQuery("from LineItem ol where ol.order.id.customerId = 'C111'").list();
t.commit();
s.close();
}
@Test
public void testCompositeIds() {
Session s = openSession();
Transaction t = s.beginTransaction();
Product p = new Product();
p.setProductId("A123");
p.setDescription("nipple ring");
p.setPrice( new BigDecimal(1.0) );
p.setNumberAvailable(1004);
s.persist(p);
Product p2 = new Product();
p2.setProductId("X525");
p2.setDescription("nose stud");
p2.setPrice( new BigDecimal(3.0) );
p2.setNumberAvailable(105);
s.persist(p2);
Customer c = new Customer();
c.setAddress("St Kilda Rd, MEL, 3000");
c.setName("Virginia");
c.setCustomerId("C111");
s.persist(c);
Order o = new Order(c);
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem(o, p);
li.setQuantity(2);
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
o = (Order) s.get( Order.class, new Order.Id("C111", 0) );
assertEquals( o.getTotal().intValue(), 2 );
o.getCustomer().getName();
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
s.createQuery("from Customer c left join fetch c.orders o left join fetch o.lineItems li left join fetch li.product p").list();
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
s.createQuery("from Order o left join fetch o.lineItems li left join fetch li.product p").list();
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
Iterator iter = s.createQuery("select o.id, li.id from Order o join o.lineItems li").list().iterator();
while ( iter.hasNext() ) {
Object[] stuff = (Object[]) iter.next();
assertTrue(stuff.length==2);
@DomainModel(
xmlMappings = {
"org/hibernate/test/cid/Customer.hbm.xml",
"org/hibernate/test/cid/Order.hbm.xml",
"org/hibernate/test/cid/LineItem.hbm.xml",
"org/hibernate/test/cid/Product.hbm.xml"
}
iter = s.createQuery("from Order o join o.lineItems li").list().iterator();
while ( iter.hasNext() ) {
Object[] stuff = (Object[]) iter.next();
assertTrue(stuff.length==2);
}
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Customer) s.get( Customer.class, "C111" );
Order o2 = new Order(c);
o2.setOrderDate( Calendar.getInstance() );
s.flush();
LineItem li2 = new LineItem(o2, p2);
li2.setQuantity(5);
List bigOrders = s.createQuery("from Order o where o.total>10.0").list();
assertEquals( bigOrders.size(), 1 );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
s.createQuery("delete from LineItem").executeUpdate();
s.createQuery("delete from Order").executeUpdate();
s.createQuery("delete from Customer").executeUpdate();
s.createQuery("delete from Product").executeUpdate();
t.commit();
s.close();
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class CompositeIdTest {
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from LineItem" ).executeUpdate();
session.createQuery( "delete from Order" ).executeUpdate();
session.createQuery( "delete from Customer" ).executeUpdate();
session.createQuery( "delete from Product" ).executeUpdate();
}
);
}
@Test
public void testNonLazyFetch() {
Session s = openSession();
Transaction t = s.beginTransaction();
Product p = new Product();
p.setProductId("A123");
p.setDescription("nipple ring");
p.setPrice( new BigDecimal(1.0) );
p.setNumberAvailable(1004);
s.persist(p);
Product p2 = new Product();
p2.setProductId("X525");
p2.setDescription("nose stud");
p2.setPrice( new BigDecimal(3.0) );
p2.setNumberAvailable(105);
s.persist(p2);
Customer c = new Customer();
c.setAddress("St Kilda Rd, MEL, 3000");
c.setName("Virginia");
c.setCustomerId("C111");
s.persist(c);
Order o = new Order(c);
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem(o, p);
li.setQuantity(2);
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
o = (Order) s.get( Order.class, new Order.Id("C111", 0) );
assertEquals( o.getTotal().intValue(), 2 );
o.getCustomer().getName();
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
o = (Order) s.createQuery("from Order o left join fetch o.lineItems li left join fetch li.product p").uniqueResult();
assertTrue( Hibernate.isInitialized( o.getLineItems() ) );
li = (LineItem) o.getLineItems().iterator().next();
assertTrue( Hibernate.isInitialized( li ) );
assertTrue( Hibernate.isInitialized( li.getProduct() ) );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
o = (Order) s.createQuery("from Order o").uniqueResult();
assertTrue( Hibernate.isInitialized( o.getLineItems() ) );
li = (LineItem) o.getLineItems().iterator().next();
assertTrue( Hibernate.isInitialized( li ) );
assertFalse( Hibernate.isInitialized( li.getProduct() ) );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
s.createQuery("delete from LineItem").executeUpdate();
s.createQuery("delete from Order").executeUpdate();
s.createQuery("delete from Customer").executeUpdate();
s.createQuery("delete from Product").executeUpdate();
t.commit();
s.close();
public void testQuery(SessionFactoryScope scope) {
scope.inTransaction(
session ->
session.createQuery( "from LineItem ol where ol.order.id.customerId = 'C111'" ).list()
);
}
@Test
public void testMultipleCollectionFetch() {
Session s = openSession();
Transaction t = s.beginTransaction();
public void testCompositeIds(SessionFactoryScope scope) {
Product p = new Product();
p.setProductId("A123");
p.setDescription("nipple ring");
p.setPrice( new BigDecimal(1.0) );
p.setNumberAvailable(1004);
s.persist(p);
p.setProductId( "A123" );
p.setDescription( "nipple ring" );
p.setPrice( new BigDecimal( 1.0 ) );
p.setNumberAvailable( 1004 );
Product p2 = new Product();
p2.setProductId("X525");
p2.setDescription("nose stud");
p2.setPrice( new BigDecimal(3.0) );
p2.setNumberAvailable(105);
s.persist(p2);
Customer c = new Customer();
c.setAddress("St Kilda Rd, MEL, 3000");
c.setName("Virginia");
c.setCustomerId("C111");
s.persist(c);
Order o = new Order(c);
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem(o, p);
li.setQuantity(2);
LineItem li2 = new LineItem(o, p2);
li2.setQuantity(3);
p2.setProductId( "X525" );
p2.setDescription( "nose stud" );
p2.setPrice( new BigDecimal( 3.0 ) );
p2.setNumberAvailable( 105 );
Order o2 = new Order(c);
o2.setOrderDate( Calendar.getInstance() );
LineItem li3 = new LineItem(o2, p);
li3.setQuantity(1);
LineItem li4 = new LineItem(o2, p2);
li4.setQuantity(1);
scope.inTransaction(
session -> {
session.persist( p );
session.persist( p2 );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
c = (Customer) s.createQuery("from Customer c left join fetch c.orders o left join fetch o.lineItems li left join fetch li.product p").uniqueResult();
assertTrue( Hibernate.isInitialized( c.getOrders() ) );
assertEquals( c.getOrders().size(), 2 );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get(0) ).getLineItems() ) );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get(1) ).getLineItems() ) );
assertEquals( ( (Order) c.getOrders().get(0) ).getLineItems().size(), 2 );
assertEquals( ( (Order) c.getOrders().get(1) ).getLineItems().size(), 2 );
t.commit();
s.close();
s = openSession();
t = s.beginTransaction();
s.createQuery("delete from LineItem").executeUpdate();
s.createQuery("delete from Order").executeUpdate();
s.createQuery("delete from Customer").executeUpdate();
s.createQuery("delete from Product").executeUpdate();
t.commit();
s.close();
Customer c = new Customer();
c.setAddress( "St Kilda Rd, MEL, 3000" );
c.setName( "Virginia" );
c.setCustomerId( "C111" );
session.persist( c );
Order o = new Order( c );
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem( o, p );
li.setQuantity( 2 );
}
);
final SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
Order o = session.get( Order.class, new Order.Id( "C111", 0 ) );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"join", 1 );
assertEquals( o.getTotal().intValue(), 2 );
o.getCustomer().getName();
}
);
statementInspector.clear();
scope.inTransaction(
session -> {
session.createQuery(
"from Customer c left join fetch c.orders o left join fetch o.lineItems li left join fetch li.product p" )
.list();
statementInspector.assertExecutedCount( 1 );
}
);
statementInspector.clear();
scope.inTransaction(
session -> {
session.createQuery( "from Order o left join fetch o.lineItems li left join fetch li.product p" )
.list();
statementInspector.assertExecutedCount( 1 );
}
);
statementInspector.clear();
scope.inTransaction(
session -> {
Iterator iter = session.createQuery( "select o.id, li.id from Order o join o.lineItems li" )
.list()
.iterator();
statementInspector.assertExecutedCount( 1 );
while ( iter.hasNext() ) {
Object[] stuff = (Object[]) iter.next();
assertTrue( stuff.length == 2 );
}
statementInspector.assertExecutedCount( 1 );
statementInspector.clear();
iter = session.createQuery( "from Order o join o.lineItems li" ).list().iterator();
statementInspector.assertExecutedCount( 1 );
while ( iter.hasNext() ) {
Object[] stuff = (Object[]) iter.next();
assertTrue( stuff.length == 2 );
}
statementInspector.assertExecutedCount( 1 );
}
);
statementInspector.clear();
scope.inTransaction(
session -> {
Customer c = session.get( Customer.class, "C111" );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"join", 0 );
statementInspector.clear();
Order o2 = new Order( c );
o2.setOrderDate( Calendar.getInstance() );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"join", 0 );
statementInspector.assertNumberOfOccurrenceInQuery( 1,"join", 0 );
statementInspector.clear();
session.flush();
statementInspector.assertExecutedCount( 4 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"select", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"join", 0 );
statementInspector.assertNumberOfOccurrenceInQuery( 1,"insert", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 2,"update", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 3,"update", 1 );
LineItem li2 = new LineItem( o2, p2 );
li2.setQuantity( 5 );
statementInspector.clear();
List bigOrders = session.createQuery( "from Order o where o.total>10.0" ).list();
statementInspector.assertExecutedCount( 3 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"select", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0,"join", 0 );
statementInspector.assertNumberOfOccurrenceInQuery( 1,"insert", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 2,"select", 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 3,"join", 0 );
assertEquals( bigOrders.size(), 1 );
}
);
}
@Test
public void testNonLazyFetch(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Product p = new Product();
p.setProductId( "A123" );
p.setDescription( "nipple ring" );
p.setPrice( new BigDecimal( 1.0 ) );
p.setNumberAvailable( 1004 );
session.persist( p );
Product p2 = new Product();
p2.setProductId( "X525" );
p2.setDescription( "nose stud" );
p2.setPrice( new BigDecimal( 3.0 ) );
p2.setNumberAvailable( 105 );
session.persist( p2 );
Customer c = new Customer();
c.setAddress( "St Kilda Rd, MEL, 3000" );
c.setName( "Virginia" );
c.setCustomerId( "C111" );
session.persist( c );
Order o = new Order( c );
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem( o, p );
li.setQuantity( 2 );
}
);
scope.inTransaction(
session -> {
Order o = session.get( Order.class, new Order.Id( "C111", 0 ) );
assertEquals( o.getTotal().intValue(), 2 );
o.getCustomer().getName();
}
);
scope.inTransaction(
session -> {
Order o = (Order) session.createQuery(
"from Order o left join fetch o.lineItems li left join fetch li.product p" )
.uniqueResult();
assertTrue( Hibernate.isInitialized( o.getLineItems() ) );
LineItem li = (LineItem) o.getLineItems().iterator().next();
assertTrue( Hibernate.isInitialized( li ) );
assertTrue( Hibernate.isInitialized( li.getProduct() ) );
}
);
scope.inTransaction(
session -> {
Order o = (Order) session.createQuery( "from Order o" ).uniqueResult();
assertTrue( Hibernate.isInitialized( o.getLineItems() ) );
LineItem li = (LineItem) o.getLineItems().iterator().next();
assertTrue( Hibernate.isInitialized( li ) );
assertFalse( Hibernate.isInitialized( li.getProduct() ) );
}
);
}
@Test
public void testMultipleCollectionFetch(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Product p = new Product();
p.setProductId( "A123" );
p.setDescription( "nipple ring" );
p.setPrice( new BigDecimal( 1.0 ) );
p.setNumberAvailable( 1004 );
session.persist( p );
Product p2 = new Product();
p2.setProductId( "X525" );
p2.setDescription( "nose stud" );
p2.setPrice( new BigDecimal( 3.0 ) );
p2.setNumberAvailable( 105 );
session.persist( p2 );
Customer c = new Customer();
c.setAddress( "St Kilda Rd, MEL, 3000" );
c.setName( "Virginia" );
c.setCustomerId( "C111" );
session.persist( c );
Order o = new Order( c );
o.setOrderDate( Calendar.getInstance() );
LineItem li = new LineItem( o, p );
li.setQuantity( 2 );
LineItem li2 = new LineItem( o, p2 );
li2.setQuantity( 3 );
Order o2 = new Order( c );
o2.setOrderDate( Calendar.getInstance() );
LineItem li3 = new LineItem( o2, p );
li3.setQuantity( 1 );
LineItem li4 = new LineItem( o2, p2 );
li4.setQuantity( 1 );
}
);
scope.inTransaction(
session -> {
Customer c = (Customer) session.createQuery(
"from Customer c left join fetch c.orders o left join fetch o.lineItems li left join fetch li.product p" )
.uniqueResult();
assertTrue( Hibernate.isInitialized( c.getOrders() ) );
assertEquals( c.getOrders().size(), 2 );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get( 0 ) ).getLineItems() ) );
assertTrue( Hibernate.isInitialized( ( (Order) c.getOrders().get( 1 ) ).getLineItems() ) );
assertEquals( 2, ( (Order) c.getOrders().get( 0 ) ).getLineItems().size() );
assertEquals( 2, ( (Order) c.getOrders().get( 1 ) ).getLineItems().size() );
}
);
}
}