HHH-7841 - Redesign Loader

This commit is contained in:
Gail Badner 2013-04-25 12:07:52 -07:00
parent 1337d36a79
commit dfe33ffa1a
7 changed files with 629 additions and 24 deletions

View File

@ -31,6 +31,7 @@ import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.entity.EntityPersister;
@ -78,7 +79,7 @@ public class CompositeFetch extends AbstractSingularAttributeFetch {
@Override
public CompositeFetch buildCompositeFetch(
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
return null; //To change body of implemented methods use File | Settings | File Templates.
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
}
@Override

View File

@ -111,6 +111,7 @@ import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.Value;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
@ -130,6 +131,7 @@ import org.hibernate.sql.Update;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
@ -5120,13 +5122,13 @@ public abstract class AbstractEntityPersister
final Type idType = getIdentifierType();
if ( !idType.isComponentType() ) {
entityIdentifierDefinition = buildEncapsulatedIdentifierDefinition();
entityIdentifierDefinition = buildSimpleEncapsulatedIdentifierDefinition();
return;
}
final CompositeType cidType = (CompositeType) idType;
if ( !cidType.isEmbedded() ) {
entityIdentifierDefinition = buildEncapsulatedIdentifierDefinition();
entityIdentifierDefinition = buildEncapsulatedCompositeIdentifierDefinition();
return;
}
@ -5155,7 +5157,7 @@ public abstract class AbstractEntityPersister
};
}
private EntityIdentifierDefinition buildEncapsulatedIdentifierDefinition() {
private EntityIdentifierDefinition buildSimpleEncapsulatedIdentifierDefinition() {
final AttributeDefinition simpleIdentifierAttributeAdapter = new AttributeDefinition() {
@Override
public String getName() {
@ -5196,6 +5198,55 @@ public abstract class AbstractEntityPersister
};
}
private EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition() {
final CompositionDefinition compositeIdentifierAttributeAdapter = new CompositionDefinition() {
@Override
public String getName() {
return entityMetamodel.getIdentifierProperty().getName();
}
@Override
public Type getType() {
return entityMetamodel.getIdentifierProperty().getType();
}
@Override
public AttributeSource getSource() {
return AbstractEntityPersister.this;
}
@Override
public String toString() {
return "<identifier-property:" + getName() + ">";
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
ComponentType componentType = (ComponentType) getType();
//for ( Type type : componentType.getSubtypes() ) {
throw new NotYetImplementedException( "cannot create sub-attribute definitions for a ComponentType yet." );
//}
}
};
return new EncapsulatedEntityIdentifierDefinition() {
@Override
public AttributeDefinition getAttributeDefinition() {
return compositeIdentifierAttributeAdapter;
}
@Override
public boolean isEncapsulated() {
return true;
}
@Override
public EntityDefinition getEntityDefinition() {
return AbstractEntityPersister.this;
}
};
}
private void collectAttributeDefinitions() {
// todo : leverage the attribute definitions housed on EntityMetamodel
// for that to work, we'd have to be able to walk our super entity persister(s)

View File

@ -72,21 +72,21 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
public Iterator<AttributeDefinition> iterator() {
return new Iterator<AttributeDefinition>() {
private final int numberOfAttributes = getType().getSubtypes().length;
private int currentAttributeNumber = 0;
private int currentSubAttributeNumber = 0;
private int currentColumnPosition = 0;
@Override
public boolean hasNext() {
return currentAttributeNumber < numberOfAttributes;
return currentSubAttributeNumber < numberOfAttributes;
}
@Override
public AttributeDefinition next() {
final int attributeNumber = currentAttributeNumber;
currentAttributeNumber++;
final int subAttributeNumber = currentSubAttributeNumber;
currentSubAttributeNumber++;
final String name = getType().getPropertyNames()[attributeNumber];
final Type type = getType().getSubtypes()[attributeNumber];
final String name = getType().getPropertyNames()[subAttributeNumber];
final Type type = getType().getSubtypes()[subAttributeNumber];
int columnPosition = currentColumnPosition;
currentColumnPosition += type.getColumnSpan( sessionFactory() );
@ -122,7 +122,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
return new CompositeBasedAssociationAttribute(
AbstractCompositionDefinition.this,
sessionFactory(),
currentAttributeNumber,
subAttributeNumber,
name,
(AssociationType) type,
new BaselineAttributeInformation.Builder()
@ -130,11 +130,11 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
.setDirtyCheckable( true )
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation(),
AbstractCompositionDefinition.this.attributeNumber(),
associationKey
@ -144,7 +144,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
return new CompositionBasedCompositionAttribute(
AbstractCompositionDefinition.this,
sessionFactory(),
currentAttributeNumber,
subAttributeNumber,
name,
(CompositeType) type,
new BaselineAttributeInformation.Builder()
@ -152,11 +152,11 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
.setDirtyCheckable( true )
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation()
);
}
@ -164,7 +164,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
return new CompositeBasedBasicAttribute(
AbstractCompositionDefinition.this,
sessionFactory(),
currentAttributeNumber,
subAttributeNumber,
name,
type,
new BaselineAttributeInformation.Builder()
@ -172,11 +172,11 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
.setDirtyCheckable( true )
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
.createInformation()
);
}

View File

@ -0,0 +1,338 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.loader;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.Id;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
import org.hibernate.loader.internal.ResultSetProcessorImpl;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.ExtraAssertions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
/**
* @author Gail Badner
*/
public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Person.class, Customer.class };
}
@Test
public void testSimpleNestedCompositeAttributeProcessing() throws Exception {
// create some test data
Session session = openSession();
session.beginTransaction();
Person person = new Person();
person.id = 1;
person.name = "Joe Blow";
person.address = new Address();
person.address.address1 = "1313 Mockingbird Lane";
person.address.city = "Pleasantville";
person.address.country = "USA";
AddressType addressType = new AddressType();
addressType.typeName = "snail mail";
person.address.type = addressType;
session.save( person );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
Person personGotten = (Person) session.get( Person.class, person.id );
assertEquals( person.id, personGotten.id );
assertEquals( person.address.address1, personGotten.address.address1 );
assertEquals( person.address.city, personGotten.address.city );
assertEquals( person.address.country, personGotten.address.country );
assertEquals( person.address.type.typeName, personGotten.address.type.typeName );
session.getTransaction().commit();
session.close();
List results = getResults( sessionFactory().getEntityPersister( Person.class.getName() ) );
assertEquals( 1, results.size() );
Object result = results.get( 0 );
assertNotNull( result );
Person personWork = ExtraAssertions.assertTyping( Person.class, result );
assertEquals( person.id, personWork.id );
assertEquals( person.address.address1, personWork.address.address1 );
assertEquals( person.address.city, personWork.address.city );
assertEquals( person.address.country, personWork.address.country );
assertEquals( person.address.type.typeName, personGotten.address.type.typeName );
// clean up test data
session = openSession();
session.beginTransaction();
session.createQuery( "delete Person" ).executeUpdate();
session.getTransaction().commit();
session.close();
}
/*
@Test
public void testNestedCompositeElementCollectionProcessing() throws Exception {
// create some test data
Session session = openSession();
session.beginTransaction();
Customer customer = new Customer();
customer.id = 1L;
Investment investment1 = new Investment();
investment1.description = "stock";
investment1.date = new Date();
investment1.monetaryAmount = new MonetaryAmount();
investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD;
investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 );
Investment investment2 = new Investment();
investment2.description = "bond";
investment2.date = new Date();
investment2.monetaryAmount = new MonetaryAmount();
investment2.monetaryAmount.currency = MonetaryAmount.CurrencyCode.EUR;
investment2.monetaryAmount.amount = BigDecimal.valueOf( 98176, 1 );
customer.investments.add( investment1 );
customer.investments.add( investment2 );
session.save( customer );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
Customer customerGotten = (Customer) session.get( Customer.class, customer.id );
assertEquals( customer.id, customerGotten.id );
session.getTransaction().commit();
session.close();
List results = getResults( sessionFactory().getEntityPersister( Customer.class.getName() ) );
assertEquals( 2, results.size() );
assertSame( results.get( 0 ), results.get( 1 ) );
Object result = results.get( 0 );
assertNotNull( result );
Customer customerWork = ExtraAssertions.assertTyping( Customer.class, result );
// clean up test data
session = openSession();
session.beginTransaction();
session.createQuery( "delete Customer" ).executeUpdate();
session.getTransaction().commit();
session.close();
}
*/
private List<?> getResults(EntityPersister entityPersister ) {
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE
);
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
final LoadQueryAliasResolutionContext aliasResolutionContext =
new LoadQueryAliasResolutionContextImpl(
sessionFactory(),
0,
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
);
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
LoadQueryInfluencers.NONE,
plan
);
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
final List results = new ArrayList();
final Session workSession = openSession();
workSession.beginTransaction();
workSession.doWork(
new Work() {
@Override
public void execute(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement( sql );
ps.setInt( 1, 1 );
ResultSet resultSet = ps.executeQuery();
results.addAll(
resultSetProcessor.extractResults(
NoOpLoadPlanAdvisor.INSTANCE,
resultSet,
(SessionImplementor) workSession,
new QueryParameters(),
new NamedParameterContext() {
@Override
public int[] getNamedParameterLocations(String name) {
return new int[0];
}
},
aliasResolutionContext,
true,
false,
null,
null
)
);
resultSet.close();
ps.close();
}
}
);
workSession.getTransaction().commit();
workSession.close();
return results;
}
@Entity( name = "Person" )
public static class Person implements Serializable {
@Id
Integer id;
String name;
@Embedded
Address address;
}
@Embeddable
public static class Address implements Serializable {
String address1;
String city;
String country;
AddressType type;
}
@Embeddable
public static class AddressType {
String typeName;
}
@Entity( name = "Customer" )
public static class Customer {
private Long id;
private List<Investment> investments = new ArrayList<Investment>();
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ElementCollection(fetch = FetchType.EAGER)
public List<Investment> getInvestments() {
return investments;
}
public void setInvestments(List<Investment> investments) {
this.investments = investments;
}
}
@Embeddable
public static class Investment {
private MonetaryAmount monetaryAmount;
private String description;
private Date date;
@Embedded
public MonetaryAmount getMonetaryAmount() {
return monetaryAmount;
}
public void setMonetaryAmount(MonetaryAmount monetaryAmount) {
this.monetaryAmount = monetaryAmount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
@Embeddable
public static class MonetaryAmount {
public static enum CurrencyCode {
USD,
EUR
}
private BigDecimal amount;
@Column(length = 3)
@Enumerated(EnumType.STRING)
private CurrencyCode currency;
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public CurrencyCode getCurrency() {
return currency;
}
public void setCurrency(CurrencyCode currency) {
this.currency = currency;
}
}
}

View File

@ -67,7 +67,7 @@ import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
public class EntityWithCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase {
public class EntityWithNonLazyCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {

View File

@ -0,0 +1,215 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.loader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.junit.Test;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
import org.hibernate.loader.internal.ResultSetProcessorImpl;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.ExtraAssertions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Gail Badner
*/
public class EntityWithNonLazyOneToManyListResultSetProcessorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Poster.class, Message.class };
}
@Test
public void testEntityWithList() throws Exception {
final EntityPersister entityPersister = sessionFactory().getEntityPersister( Poster.class.getName() );
// create some test data
Session session = openSession();
session.beginTransaction();
Poster poster = new Poster();
poster.pid = 0;
poster.name = "John Doe";
Message message1 = new Message();
message1.mid = 1;
message1.msgTxt = "Howdy!";
message1.poster = poster;
poster.messages.add( message1 );
Message message2 = new Message();
message2.mid = 2;
message2.msgTxt = "Bye!";
message2.poster = poster;
poster.messages.add( message2 );
session.save( poster );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
Poster posterGotten = (Poster) session.get( Poster.class, poster.pid );
assertEquals( 0, posterGotten.pid.intValue() );
assertEquals( poster.name, posterGotten.name );
assertTrue( Hibernate.isInitialized( posterGotten.messages ) );
assertEquals( 2, posterGotten.messages.size() );
assertEquals( message1.msgTxt, posterGotten.messages.get( 0 ).msgTxt );
assertEquals( message2.msgTxt, posterGotten.messages.get( 1 ).msgTxt );
assertSame( posterGotten, posterGotten.messages.get( 0 ).poster );
assertSame( posterGotten, posterGotten.messages.get( 1 ).poster );
session.getTransaction().commit();
session.close();
{
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE
);
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
final LoadQueryAliasResolutionContext aliasResolutionContext =
new LoadQueryAliasResolutionContextImpl(
sessionFactory(),
0,
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
);
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
LoadQueryInfluencers.NONE,
plan
);
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
final List results = new ArrayList();
final Session workSession = openSession();
workSession.beginTransaction();
workSession.doWork(
new Work() {
@Override
public void execute(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement( sql );
ps.setInt( 1, 0 );
ResultSet resultSet = ps.executeQuery();
results.addAll(
resultSetProcessor.extractResults(
NoOpLoadPlanAdvisor.INSTANCE,
resultSet,
(SessionImplementor) workSession,
new QueryParameters(),
new NamedParameterContext() {
@Override
public int[] getNamedParameterLocations(String name) {
return new int[0];
}
},
aliasResolutionContext,
true,
false,
null,
null
)
);
resultSet.close();
ps.close();
}
}
);
assertEquals( 2, results.size() );
Object result1 = results.get( 0 );
assertNotNull( result1 );
assertSame( result1, results.get( 1 ) );
Poster workPoster = ExtraAssertions.assertTyping( Poster.class, result1 );
assertEquals( 0, workPoster.pid.intValue() );
assertEquals( poster.name, workPoster.name );
assertTrue( Hibernate.isInitialized( workPoster.messages ) );
assertEquals( 2, workPoster.messages.size() );
assertTrue( Hibernate.isInitialized( posterGotten.messages ) );
assertEquals( 2, workPoster.messages.size() );
assertEquals( message1.msgTxt, workPoster.messages.get( 0 ).msgTxt );
assertEquals( message2.msgTxt, workPoster.messages.get( 1 ).msgTxt );
assertSame( workPoster, workPoster.messages.get( 0 ).poster );
assertSame( workPoster, workPoster.messages.get( 1 ).poster );
workSession.getTransaction().commit();
workSession.close();
}
// clean up test data
session = openSession();
session.beginTransaction();
session.delete( poster );
session.getTransaction().commit();
session.close();
}
@Entity( name = "Message" )
public static class Message {
@Id
private Integer mid;
private String msgTxt;
@ManyToOne
@JoinColumn
private Poster poster;
}
@Entity( name = "Poster" )
public static class Poster {
@Id
private Integer pid;
private String name;
@OneToMany(mappedBy = "poster", fetch = FetchType.EAGER, cascade = CascadeType.ALL )
private List<Message> messages = new ArrayList<Message>();
}
}

View File

@ -70,7 +70,7 @@ import static org.junit.Assert.fail;
/**
* @author Gail Badner
*/
public class EntityWithOneToManyResultSetProcessorTest extends BaseCoreFunctionalTestCase {
public class EntityWithNonLazyOneToManySetResultSetProcessorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {