diff --git a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java index 90b72e445f..6ae48a6997 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/DerivedIdentitySimpleParentSimpleDepTest.java @@ -14,55 +14,79 @@ public class DerivedIdentitySimpleParentSimpleDepTest extends TestCase { public void testOneToOneExplicitJoinColumn() throws Exception { assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", getCfg() ) ); assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", getCfg() ) ); - Person e = new Person(); - e.ssn = "aaa"; - Session s = openSession( ); - s.getTransaction().begin(); - s.persist( e ); - MedicalHistory d = new MedicalHistory(); - d.patient = e; - s.persist( d ); - s.flush(); - s.clear(); - final Class clazz = MedicalHistory.class; - d = getDerivedClassById( e, s, clazz ); - assertEquals( e.ssn, d.patient.ssn ); - d.lastupdate = new Date(); - s.flush(); - s.clear(); - d = getDerivedClassById( e, s, clazz ); - assertNotNull( d.lastupdate ); - s.getTransaction().rollback(); - s.close(); - } - private T getDerivedClassById(Person e, Session s, Class clazz) { - return ( T ) - s.createQuery( "from " + clazz.getName() + " mh where mh.patient.ssn = :ssn") - .setParameter( "ssn", e.ssn ).uniqueResult(); + Session s = openSession(); + s.getTransaction().begin(); + Person person = new Person( "aaa" ); + s.persist( person ); + MedicalHistory medicalHistory = new MedicalHistory( person ); + s.persist( medicalHistory ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + medicalHistory = (MedicalHistory) s.get( MedicalHistory.class, "aaa" ); + assertEquals( person.ssn, medicalHistory.patient.ssn ); + medicalHistory.lastupdate = new Date(); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + medicalHistory = (MedicalHistory) s.get( MedicalHistory.class, "aaa" ); + assertNotNull( medicalHistory.lastupdate ); + s.delete( medicalHistory ); + s.getTransaction().commit(); + s.close(); } public void testManyToOneExplicitJoinColumn() throws Exception { assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", getCfg() ) ); assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", getCfg() ) ); - Person e = new Person(); - e.ssn = "aaa"; - Session s = openSession( ); + + Session s = openSession(); s.getTransaction().begin(); + Person person = new Person( "aaa" ); + s.persist( person ); + FinancialHistory financialHistory = new FinancialHistory( person ); + s.persist( financialHistory ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + financialHistory = (FinancialHistory) s.get( FinancialHistory.class, "aaa" ); + assertEquals( person.ssn, financialHistory.patient.ssn ); + financialHistory.lastUpdate = new Date(); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + financialHistory = (FinancialHistory) s.get( FinancialHistory.class, "aaa" ); + assertNotNull( financialHistory.lastUpdate ); + s.delete( financialHistory ); + s.getTransaction().commit(); + s.close(); + } + + public void testSimplePkValueLoading() { + Session s = openSession(); + s.getTransaction().begin(); + Person e = new Person( "aaa" ); s.persist( e ); - FinancialHistory d = new FinancialHistory(); - d.patient = e; + FinancialHistory d = new FinancialHistory( e ); s.persist( d ); - s.flush(); - s.clear(); - d = getDerivedClassById(e, s, FinancialHistory.class); - assertEquals( e.ssn, d.patient.ssn ); - d.lastupdate = new Date(); - s.flush(); - s.clear(); - d = getDerivedClassById(e, s, FinancialHistory.class); - assertNotNull( d.lastupdate ); - s.getTransaction().rollback(); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.getTransaction().begin(); + FinancialHistory history = (FinancialHistory) s.get( FinancialHistory.class, "aaa" ); + assertNotNull( history ); + s.delete( history ); + s.getTransaction().commit(); s.close(); } diff --git a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java index 541a9ad43b..0467e155e1 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/FinancialHistory.java @@ -16,13 +16,18 @@ import javax.persistence.TemporalType; */ @Entity public class FinancialHistory implements Serializable { - - @Temporal(TemporalType.DATE) - Date lastupdate; - @Id //@JoinColumn(name = "FK") @ManyToOne Person patient; + @Temporal(TemporalType.DATE) + Date lastUpdate; + + public FinancialHistory() { + } + + public FinancialHistory(Person patient) { + this.patient = patient; + } } \ No newline at end of file diff --git a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java index 15409aba70..616f370a0c 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/MedicalHistory.java @@ -16,12 +16,18 @@ import javax.persistence.TemporalType; */ @Entity public class MedicalHistory implements Serializable { - - @Temporal(TemporalType.DATE) - Date lastupdate; - @Id @JoinColumn(name = "FK") @OneToOne Person patient; + + @Temporal(TemporalType.DATE) + Date lastupdate; + + public MedicalHistory() { + } + + public MedicalHistory(Person patient) { + this.patient = patient; + } } \ No newline at end of file diff --git a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java index e0d7a4819e..70bb12a53a 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/derivedidentities/e4/a/Person.java @@ -11,4 +11,11 @@ import javax.persistence.Id; public class Person { @Id String ssn; + + public Person() { + } + + public Person(String ssn) { + this.ssn = ssn; + } } \ No newline at end of file diff --git a/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java b/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java index 6fad0849ad..988d89e629 100644 --- a/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java +++ b/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * Copyright (c) 2010, 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 Middleware LLC. + * 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 @@ -20,7 +20,6 @@ * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA - * */ package org.hibernate.event.def; @@ -54,6 +53,8 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; +import org.hibernate.type.EmbeddedComponentType; +import org.hibernate.type.EntityType; import org.hibernate.type.Type; import org.hibernate.type.TypeFactory; @@ -106,6 +107,31 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i else { Class idClass = persister.getIdentifierType().getReturnedClass(); if ( idClass != null && ! idClass.isInstance( event.getEntityId() ) ) { + // we may have the kooky jpa requirement of allowing find-by-id where + // "id" is the "simple pk value" of a dependent objects parent. This + // is part of its generally goofy "derived identity" "feature" + if ( persister.getEntityMetamodel().getIdentifierProperty().isEmbedded() ) { + final EmbeddedComponentType dependentIdType = + (EmbeddedComponentType) persister.getEntityMetamodel().getIdentifierProperty().getType(); + if ( dependentIdType.getSubtypes().length == 1 ) { + final Type singleSubType = dependentIdType.getSubtypes()[0]; + if ( singleSubType.isEntityType() ) { + final EntityType dependentParentType = (EntityType) singleSubType; + final Type dependentParentIdType = dependentParentType.getIdentifierOrUniqueKeyType( source.getFactory() ); + if ( dependentParentIdType.getReturnedClass().isInstance( event.getEntityId() ) ) { + // yep that's what we have... + loadByDerivedIdentitySimplePkValue( + event, + loadType, + persister, + dependentIdType, + source.getFactory().getEntityPersister( dependentParentType.getAssociatedEntityName() ) + ); + return; + } + } + } + } throw new TypeMismatchException( "Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass + ", got " + event.getEntityId().getClass() ); @@ -136,6 +162,42 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i } } + private void loadByDerivedIdentitySimplePkValue( + LoadEvent event, + LoadEventListener.LoadType options, + EntityPersister dependentPersister, + EmbeddedComponentType dependentIdType, + EntityPersister parentPersister) { + final EntityKey parentEntityKey = new EntityKey( + event.getEntityId(), + parentPersister, + event.getSession().getEntityMode() + ); + final Object parent = doLoad( + event, + parentPersister, + parentEntityKey, + options + ); + + Serializable dependent = (Serializable) dependentIdType.instantiate( parent, event.getSession() ); + dependentIdType.setPropertyValues( dependent, new Object[] {parent}, event.getSession().getEntityMode() ); + final EntityKey dependentEntityKey = new EntityKey( + dependent, + dependentPersister, + event.getSession().getEntityMode() + ); + event.setEntityId( dependent ); + dependent = (Serializable) doLoad( + event, + dependentPersister, + dependentEntityKey, + options + ); + + event.setResult( dependent ); + } + /** * Perfoms the load of an entity. *