HHH-4861 - Allow lookup by the "simple" pk type of "parent entity" in "derived identities" cases
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18686 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
e2fc86d5d5
commit
c86d471453
|
@ -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<MedicalHistory> 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> T getDerivedClassById(Person e, Session s, Class<T> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -11,4 +11,11 @@ import javax.persistence.Id;
|
|||
public class Person {
|
||||
@Id
|
||||
String ssn;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String ssn) {
|
||||
this.ssn = ssn;
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue