/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.loadplans.process; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.jdbc.Work; import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessor; import org.hibernate.loader.plan.exec.query.spi.NamedParameterContext; import org.hibernate.loader.plan.exec.spi.LoadQueryDetails; import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.persister.entity.EntityPersister; import org.junit.Test; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.ExtraAssertions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * @author Gail Badner */ public class EntityAssociationResultSetProcessorTest extends BaseCoreFunctionalTestCase { @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] { Message.class, Poster.class, ReportedMessage.class }; } @Test public void testManyToOneEntityProcessing() throws Exception { final EntityPersister entityPersister = sessionFactory().getEntityPersister( Message.class.getName() ); // create some test data Session session = openSession(); session.beginTransaction(); Message message = new Message( 1, "the message" ); Poster poster = new Poster( 2, "the poster" ); session.save( message ); session.save( poster ); message.poster = poster; poster.messages.add( message ); session.getTransaction().commit(); session.close(); { final LoadPlan plan = Helper.INSTANCE.buildLoadPlan( sessionFactory(), entityPersister ); final LoadQueryDetails queryDetails = Helper.INSTANCE.buildLoadQueryDetails( plan, sessionFactory() ); final String sql = queryDetails.getSqlStatement(); final ResultSetProcessor resultSetProcessor = queryDetails.getResultSetProcessor(); 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( resultSet, (SessionImplementor) workSession, new QueryParameters(), new NamedParameterContext() { @Override public int[] getNamedParameterLocations(String name) { return new int[0]; } }, true, false, null, null ) ); resultSet.close(); ps.close(); } } ); assertEquals( 1, results.size() ); Object result = results.get( 0 ); assertNotNull( result ); Message workMessage = ExtraAssertions.assertTyping( Message.class, result ); assertEquals( 1, workMessage.mid.intValue() ); assertEquals( "the message", workMessage.msgTxt ); assertTrue( Hibernate.isInitialized( workMessage.poster ) ); Poster workPoster = workMessage.poster; assertEquals( 2, workPoster.pid.intValue() ); assertEquals( "the poster", workPoster.name ); assertFalse( Hibernate.isInitialized( workPoster.messages ) ); workSession.getTransaction().commit(); workSession.close(); } // clean up test data session = openSession(); session.beginTransaction(); session.createQuery( "delete Message" ).executeUpdate(); session.createQuery( "delete Poster" ).executeUpdate(); session.getTransaction().commit(); session.close(); } @Test public void testNestedManyToOneEntityProcessing() throws Exception { final EntityPersister entityPersister = sessionFactory().getEntityPersister( ReportedMessage.class.getName() ); // create some test data Session session = openSession(); session.beginTransaction(); Message message = new Message( 1, "the message" ); Poster poster = new Poster( 2, "the poster" ); session.save( message ); session.save( poster ); message.poster = poster; poster.messages.add( message ); ReportedMessage reportedMessage = new ReportedMessage( 0, "inappropriate", message ); session.save( reportedMessage ); session.getTransaction().commit(); session.close(); { final LoadPlan plan = Helper.INSTANCE.buildLoadPlan( sessionFactory(), entityPersister ); final LoadQueryDetails queryDetails = Helper.INSTANCE.buildLoadQueryDetails( plan, sessionFactory() ); final String sql = queryDetails.getSqlStatement(); final ResultSetProcessor resultSetProcessor = queryDetails.getResultSetProcessor(); 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( resultSet, (SessionImplementor) workSession, new QueryParameters(), new NamedParameterContext() { @Override public int[] getNamedParameterLocations(String name) { return new int[0]; } }, true, false, null, null ) ); resultSet.close(); ps.close(); } } ); assertEquals( 1, results.size() ); Object result = results.get( 0 ); assertNotNull( result ); ReportedMessage workReportedMessage = ExtraAssertions.assertTyping( ReportedMessage.class, result ); assertEquals( 0, workReportedMessage.id.intValue() ); assertEquals( "inappropriate", workReportedMessage.reason ); Message workMessage = workReportedMessage.message; assertNotNull( workMessage ); assertTrue( Hibernate.isInitialized( workMessage ) ); assertEquals( 1, workMessage.mid.intValue() ); assertEquals( "the message", workMessage.msgTxt ); assertTrue( Hibernate.isInitialized( workMessage.poster ) ); Poster workPoster = workMessage.poster; assertEquals( 2, workPoster.pid.intValue() ); assertEquals( "the poster", workPoster.name ); assertFalse( Hibernate.isInitialized( workPoster.messages ) ); workSession.getTransaction().commit(); workSession.close(); } // clean up test data session = openSession(); session.beginTransaction(); session.createQuery( "delete ReportedMessage" ).executeUpdate(); session.createQuery( "delete Message" ).executeUpdate(); session.createQuery( "delete Poster" ).executeUpdate(); session.getTransaction().commit(); session.close(); } @Entity( name = "ReportedMessage" ) public static class ReportedMessage { @Id private Integer id; private String reason; @ManyToOne @JoinColumn private Message message; public ReportedMessage() {} public ReportedMessage(Integer id, String reason, Message message) { this.id = id; this.reason = reason; this.message = message; } } @Entity( name = "Message" ) public static class Message { @Id private Integer mid; private String msgTxt; @ManyToOne( cascade = CascadeType.MERGE ) @JoinColumn private Poster poster; public Message() {} public Message(Integer mid, String msgTxt) { this.mid = mid; this.msgTxt = msgTxt; } } @Entity( name = "Poster" ) public static class Poster { @Id private Integer pid; private String name; @OneToMany(mappedBy = "poster") private List<Message> messages = new ArrayList<Message>(); public Poster() {} public Poster(Integer pid, String name) { this.pid = pid; this.name = name; } } }