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 {
|
public void testOneToOneExplicitJoinColumn() throws Exception {
|
||||||
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", getCfg() ) );
|
assertTrue( SchemaUtil.isColumnPresent( "MedicalHistory", "FK", getCfg() ) );
|
||||||
assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", getCfg() ) );
|
assertTrue( ! SchemaUtil.isColumnPresent( "MedicalHistory", "id", getCfg() ) );
|
||||||
Person e = new Person();
|
|
||||||
e.ssn = "aaa";
|
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
s.getTransaction().begin();
|
s.getTransaction().begin();
|
||||||
s.persist( e );
|
Person person = new Person( "aaa" );
|
||||||
MedicalHistory d = new MedicalHistory();
|
s.persist( person );
|
||||||
d.patient = e;
|
MedicalHistory medicalHistory = new MedicalHistory( person );
|
||||||
s.persist( d );
|
s.persist( medicalHistory );
|
||||||
s.flush();
|
s.getTransaction().commit();
|
||||||
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();
|
s.close();
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T getDerivedClassById(Person e, Session s, Class<T> clazz) {
|
s = openSession();
|
||||||
return ( T )
|
s.getTransaction().begin();
|
||||||
s.createQuery( "from " + clazz.getName() + " mh where mh.patient.ssn = :ssn")
|
medicalHistory = (MedicalHistory) s.get( MedicalHistory.class, "aaa" );
|
||||||
.setParameter( "ssn", e.ssn ).uniqueResult();
|
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 {
|
public void testManyToOneExplicitJoinColumn() throws Exception {
|
||||||
assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", getCfg() ) );
|
assertTrue( SchemaUtil.isColumnPresent( "FinancialHistory", "patient_ssn", getCfg() ) );
|
||||||
assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", getCfg() ) );
|
assertTrue( ! SchemaUtil.isColumnPresent( "FinancialHistory", "id", getCfg() ) );
|
||||||
Person e = new Person();
|
|
||||||
e.ssn = "aaa";
|
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
s.getTransaction().begin();
|
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 );
|
s.persist( e );
|
||||||
FinancialHistory d = new FinancialHistory();
|
FinancialHistory d = new FinancialHistory( e );
|
||||||
d.patient = e;
|
|
||||||
s.persist( d );
|
s.persist( d );
|
||||||
s.flush();
|
s.getTransaction().commit();
|
||||||
s.clear();
|
s.close();
|
||||||
d = getDerivedClassById(e, s, FinancialHistory.class);
|
|
||||||
assertEquals( e.ssn, d.patient.ssn );
|
s = openSession();
|
||||||
d.lastupdate = new Date();
|
s.getTransaction().begin();
|
||||||
s.flush();
|
FinancialHistory history = (FinancialHistory) s.get( FinancialHistory.class, "aaa" );
|
||||||
s.clear();
|
assertNotNull( history );
|
||||||
d = getDerivedClassById(e, s, FinancialHistory.class);
|
s.delete( history );
|
||||||
assertNotNull( d.lastupdate );
|
s.getTransaction().commit();
|
||||||
s.getTransaction().rollback();
|
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,18 @@ import javax.persistence.TemporalType;
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class FinancialHistory implements Serializable {
|
public class FinancialHistory implements Serializable {
|
||||||
|
|
||||||
@Temporal(TemporalType.DATE)
|
|
||||||
Date lastupdate;
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
//@JoinColumn(name = "FK")
|
//@JoinColumn(name = "FK")
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
Person patient;
|
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
|
@Entity
|
||||||
public class MedicalHistory implements Serializable {
|
public class MedicalHistory implements Serializable {
|
||||||
|
|
||||||
@Temporal(TemporalType.DATE)
|
|
||||||
Date lastupdate;
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@JoinColumn(name = "FK")
|
@JoinColumn(name = "FK")
|
||||||
@OneToOne
|
@OneToOne
|
||||||
Person patient;
|
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 {
|
public class Person {
|
||||||
@Id
|
@Id
|
||||||
String ssn;
|
String ssn;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(String ssn) {
|
||||||
|
this.ssn = ssn;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* 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
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* 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,
|
* 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
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.event.def;
|
package org.hibernate.event.def;
|
||||||
|
|
||||||
|
@ -54,6 +53,8 @@ import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.proxy.LazyInitializer;
|
import org.hibernate.proxy.LazyInitializer;
|
||||||
|
import org.hibernate.type.EmbeddedComponentType;
|
||||||
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeFactory;
|
import org.hibernate.type.TypeFactory;
|
||||||
|
|
||||||
|
@ -106,6 +107,31 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
||||||
else {
|
else {
|
||||||
Class idClass = persister.getIdentifierType().getReturnedClass();
|
Class idClass = persister.getIdentifierType().getReturnedClass();
|
||||||
if ( idClass != null && ! idClass.isInstance( event.getEntityId() ) ) {
|
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(
|
throw new TypeMismatchException(
|
||||||
"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass + ", got " + event.getEntityId().getClass()
|
"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.
|
* Perfoms the load of an entity.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue