/*
* 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 java.io.Serializable;
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 javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.LockOptions;
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.hibernate.type.Type;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.ExtraAssertions;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Gail Badner
*/
public class EncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Parent.class, CardField.class, Card.class };
}
@Test
public void testSimpleCompositeId() throws Exception {
// create some test data
Session session = openSession();
session.beginTransaction();
Parent parent = new Parent();
parent.id = new ParentPK();
parent.id.firstName = "Joe";
parent.id.lastName = "Blow";
session.save( parent );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
Parent parentGotten = (Parent) session.get( Parent.class, parent.id );
assertEquals( parent, parentGotten );
session.getTransaction().commit();
session.close();
final List results = getResults(
sessionFactory().getEntityPersister( Parent.class.getName() ),
new Callback() {
@Override
public void bind(PreparedStatement ps) throws SQLException {
ps.setString( 1, "Joe" );
ps.setString( 2, "Blow" );
}
@Override
public QueryParameters getQueryParameters() {
return new QueryParameters();
}
}
);
assertEquals( 1, results.size() );
Object result = results.get( 0 );
assertNotNull( result );
Parent parentWork = ExtraAssertions.assertTyping( Parent.class, result );
assertEquals( parent, parentWork );
// clean up test data
session = openSession();
session.beginTransaction();
session.createQuery( "delete Parent" ).executeUpdate();
session.getTransaction().commit();
session.close();
}
@Test
public void testCompositeIdWithKeyManyToOne() throws Exception {
final String cardId = "ace-of-spades";
// create some test data
Session session = openSession();
session.beginTransaction();
Card card = new Card( cardId );
final CardField cardField = new CardField( card, 1 );
session.persist( card );
session.persist( cardField );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
Card cardProxy = (Card) session.load( Card.class, cardId );
final CardFieldPK cardFieldPK = new CardFieldPK( cardProxy, 1 );
CardField cardFieldGotten = (CardField) session.get( CardField.class, cardFieldPK );
//assertEquals( card, cardGotten );
session.getTransaction().commit();
session.close();
final EntityPersister entityPersister = sessionFactory().getEntityPersister( CardField.class.getName() );
final List results = getResults(
entityPersister,
new Callback() {
@Override
public void bind(PreparedStatement ps) throws SQLException {
ps.setString( 1, cardField.primaryKey.card.id );
ps.setInt( 2, cardField.primaryKey.fieldNumber );
}
@Override
public QueryParameters getQueryParameters() {
QueryParameters qp = new QueryParameters();
qp.setPositionalParameterTypes( new Type[] { entityPersister.getIdentifierType() } );
qp.setPositionalParameterValues( new Object[] { cardFieldPK } );
qp.setOptionalObject( null );
qp.setOptionalEntityName( entityPersister.getEntityName() );
qp.setOptionalId( cardFieldPK );
qp.setLockOptions( LockOptions.NONE );
return qp;
}
}
);
assertEquals( 1, results.size() );
Object result = results.get( 0 );
assertNotNull( result );
CardField cardFieldWork = ExtraAssertions.assertTyping( CardField.class, result );
assertEquals( cardFieldGotten, cardFieldWork );
// clean up test data
session = openSession();
session.beginTransaction();
session.createQuery( "delete CardField" ).executeUpdate();
session.createQuery( "delete Card" ).executeUpdate();
session.getTransaction().commit();
session.close();
}
private List getResults(final EntityPersister entityPersister, final Callback callback) {
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 );
callback.bind( ps );
ResultSet resultSet = ps.executeQuery();
//callback.beforeExtractResults( workSession );
results.addAll(
resultSetProcessor.extractResults(
resultSet,
(SessionImplementor) workSession,
callback.getQueryParameters(),
new NamedParameterContext() {
@Override
public int[] getNamedParameterLocations(String name) {
return new int[0];
}
},
true,
false,
null,
null
)
);
resultSet.close();
ps.close();
}
}
);
workSession.getTransaction().commit();
workSession.close();
return results;
}
private interface Callback {
void bind(PreparedStatement ps) throws SQLException;
QueryParameters getQueryParameters ();
}
@Entity ( name = "Parent" )
public static class Parent {
@EmbeddedId
public ParentPK id;
public boolean equals(Object o) {
if ( this == o ) return true;
if ( !( o instanceof Parent ) ) return false;
final Parent parent = (Parent) o;
if ( !id.equals( parent.id ) ) return false;
return true;
}
public int hashCode() {
return id.hashCode();
}
}
@Embeddable
public static class ParentPK implements Serializable {
private String firstName;
private String lastName;
public boolean equals(Object o) {
if ( this == o ) return true;
if ( !( o instanceof ParentPK ) ) return false;
final ParentPK parentPk = (ParentPK) o;
if ( !firstName.equals( parentPk.firstName ) ) return false;
if ( !lastName.equals( parentPk.lastName ) ) return false;
return true;
}
public int hashCode() {
int result;
result = firstName.hashCode();
result = 29 * result + lastName.hashCode();
return result;
}
}
@Entity ( name = "CardField" )
public static class CardField implements Serializable {
@EmbeddedId
private CardFieldPK primaryKey;
CardField(Card card, int fieldNumber) {
this.primaryKey = new CardFieldPK(card, fieldNumber);
}
CardField() {
}
public CardFieldPK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(CardFieldPK primaryKey) {
this.primaryKey = primaryKey;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
CardField cardField = (CardField) o;
if ( primaryKey != null ? !primaryKey.equals( cardField.primaryKey ) : cardField.primaryKey != null ) {
return false;
}
return true;
}
@Override
public int hashCode() {
return primaryKey != null ? primaryKey.hashCode() : 0;
}
}
@Embeddable
public static class CardFieldPK implements Serializable {
@ManyToOne(optional = false)
private Card card;
private int fieldNumber;
public CardFieldPK(Card card, int fieldNumber) {
this.card = card;
this.fieldNumber = fieldNumber;
}
CardFieldPK() {
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
public int getFieldNumber() {
return fieldNumber;
}
public void setFieldNumber(int fieldNumber) {
this.fieldNumber = fieldNumber;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
CardFieldPK that = (CardFieldPK) o;
if ( fieldNumber != that.fieldNumber ) {
return false;
}
if ( card != null ? !card.equals( that.card ) : that.card != null ) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = card != null ? card.hashCode() : 0;
result = 31 * result + fieldNumber;
return result;
}
}
@Entity ( name = "Card" )
public static class Card implements Serializable {
@Id
private String id;
public Card(String id) {
this();
this.id = id;
}
Card() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Card card = (Card) o;
if ( !id.equals( card.id ) ) {
return false;
}
return true;
}
@Override
public int hashCode() {
return id.hashCode();
}
}
}