HHH-4848 partial implementation of @IdClass support in derivedidentity (example 1 case a of the spec)
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18692 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
cffff168b3
commit
252299cfee
|
@ -55,6 +55,7 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
|||
private Map<String, JoinTable> currentPropertyJoinTableOverride;
|
||||
private String path;
|
||||
private ExtendedMappings mappings;
|
||||
private Boolean isInIdClass;
|
||||
|
||||
|
||||
public AbstractPropertyHolder(
|
||||
|
@ -66,6 +67,15 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
|||
buildHierarchyColumnOverride( clazzToProcess );
|
||||
}
|
||||
|
||||
|
||||
public boolean isInIdClass() {
|
||||
return isInIdClass != null ? isInIdClass : parent != null ? parent.isInIdClass() : false;
|
||||
}
|
||||
|
||||
public void setInIdClass(Boolean isInIdClass) {
|
||||
this.isInIdClass = isInIdClass;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
|
|
@ -701,6 +701,7 @@ public final class
|
|||
HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
|
||||
boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();
|
||||
entityBinder.setIgnoreIdAnnotations( true );
|
||||
propertyHolder.setInIdClass( true );
|
||||
bindId(
|
||||
generatorType,
|
||||
generator,
|
||||
|
@ -716,6 +717,7 @@ public final class
|
|||
mappings,
|
||||
inheritanceStatePerClass
|
||||
);
|
||||
propertyHolder.setInIdClass( null );
|
||||
inferredData = new PropertyPreloadedData(
|
||||
propertyAccessor, "_identifierMapper", compositeClass
|
||||
);
|
||||
|
@ -728,7 +730,9 @@ public final class
|
|||
entityBinder,
|
||||
true,
|
||||
true,
|
||||
false, mappings, inheritanceStatePerClass
|
||||
false,
|
||||
mappings,
|
||||
inheritanceStatePerClass
|
||||
);
|
||||
entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
|
||||
persistentClass.setIdentifierMapper( mapper );
|
||||
|
@ -1164,7 +1168,7 @@ public final class
|
|||
* strategy is used
|
||||
* @param propertyContainer Metadata about a class and its properties
|
||||
* @param mappings Mapping meta data
|
||||
* @return the number of id properties found while iterating the elements of {@code annoatedClass} using
|
||||
* @return the number of id properties found while iterating the elements of {@code annotatedClass} using
|
||||
* the determined access strategy, {@code false} otherwise.
|
||||
*/
|
||||
static int addElementsOfClass(
|
||||
|
@ -1206,6 +1210,9 @@ public final class
|
|||
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
|
||||
if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
|
||||
annElts.add( 0, propertyAnnotatedElement );
|
||||
if ( element.isAnnotationPresent( ManyToOne.class ) || element.isAnnotationPresent( OneToOne.class ) ) {
|
||||
mappings.addToOneAndIdProperty( entity, propertyAnnotatedElement );
|
||||
}
|
||||
idPropertyCounter++;
|
||||
}
|
||||
else {
|
||||
|
@ -1713,15 +1720,15 @@ public final class
|
|||
//FIXME do the overrideColumnFromMapsIdProperty here and force the idclass type to look like an @embedded
|
||||
//Overrides from @MapsId if needed
|
||||
boolean isOverridden = false;
|
||||
if ( isId || propertyHolder.isOrWithinEmbeddedId() ) {
|
||||
if ( isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
|
||||
Ejb3Column[] oldColumns = columns;
|
||||
columns = columnsBuilder.overrideColumnFromMapsIdProperty(isId);
|
||||
columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty(isId);
|
||||
isOverridden = oldColumns != columns;
|
||||
}
|
||||
if ( isComponent ) {
|
||||
String referencedEntityName = null;
|
||||
if (isOverridden) {
|
||||
final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
|
||||
final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
|
||||
isId, propertyHolder, property.getName(), mappings
|
||||
);
|
||||
referencedEntityName = mapsIdProperty.getClassOrElementName();
|
||||
|
@ -1761,7 +1768,7 @@ public final class
|
|||
propertyBinder.setLazy( lazy );
|
||||
propertyBinder.setColumns( columns );
|
||||
if (isOverridden) {
|
||||
final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
|
||||
final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
|
||||
isId, propertyHolder, property.getName(), mappings
|
||||
);
|
||||
propertyBinder.setReferencedEntityName( mapsIdProperty.getClassOrElementName() );
|
||||
|
@ -1771,7 +1778,7 @@ public final class
|
|||
|
||||
}
|
||||
if (isOverridden) {
|
||||
final PropertyData mapsIdProperty = BinderHelper.getPropertyAnnotatedWithMapsId(
|
||||
final PropertyData mapsIdProperty = BinderHelper.getPropertyOverriddenByMapperOrMapsId(
|
||||
isId, propertyHolder, property.getName(), mappings
|
||||
);
|
||||
HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators.clone();
|
||||
|
@ -2021,7 +2028,8 @@ public final class
|
|||
}
|
||||
|
||||
public static Component fillComponent(
|
||||
PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData,
|
||||
PropertyHolder propertyHolder, PropertyData inferredData,
|
||||
PropertyData baseInferredData, //base inferred data correspond to the entity reproducing inferredData's properties (ie IdClass)
|
||||
AccessType propertyAccessor, boolean isNullable, EntityBinder entityBinder,
|
||||
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings,
|
||||
Map<XClass, InheritanceState> inheritanceStatePerClass
|
||||
|
@ -2045,14 +2053,17 @@ public final class
|
|||
XClass returnedClassOrElement = inferredData.getClassOrElement();
|
||||
|
||||
List<PropertyData> baseClassElements = null;
|
||||
Map<String, PropertyData> orderedBaseClassElements = new HashMap<String, PropertyData>();
|
||||
XClass baseReturnedClassOrElement;
|
||||
if(baseInferredData != null)
|
||||
{
|
||||
if(baseInferredData != null) {
|
||||
baseClassElements = new ArrayList<PropertyData>();
|
||||
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
|
||||
bindTypeDefs(baseReturnedClassOrElement, mappings);
|
||||
PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement, entityXClass );
|
||||
addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
|
||||
for (PropertyData element : baseClassElements) {
|
||||
orderedBaseClassElements.put( element.getPropertyName(), element );
|
||||
}
|
||||
}
|
||||
|
||||
//embeddable elements can have type defs
|
||||
|
@ -2069,9 +2080,24 @@ public final class
|
|||
superClass = superClass.getSuperclass();
|
||||
}
|
||||
if ( baseClassElements != null ) {
|
||||
if ( !hasIdClassAnnotations( entityXClass ) ) {
|
||||
//useful to avoid breaking pre JPA 2 mappings
|
||||
if ( !hasAnnotationsOnIdClass( entityXClass ) ) {
|
||||
for ( int i = 0; i < classElements.size(); i++ ) {
|
||||
classElements.set( i, baseClassElements.get( i ) ); //this works since they are in the same order
|
||||
final PropertyData idClassPropertyData = classElements.get( i );
|
||||
final PropertyData entityPropertyData = orderedBaseClassElements.get( idClassPropertyData.getPropertyName() );
|
||||
if ( propertyHolder.isInIdClass() ) {
|
||||
if ( entityPropertyData.getProperty().isAnnotationPresent( ManyToOne.class )
|
||||
|| entityPropertyData.getProperty().isAnnotationPresent( OneToOne.class ) ) {
|
||||
//don't replace here as we need to use the actual original return type
|
||||
//the annotation overriding will be dealt with by a mechanism similar to @MapsId
|
||||
}
|
||||
else {
|
||||
classElements.set( i, entityPropertyData ); //this works since they are in the same order
|
||||
}
|
||||
}
|
||||
else {
|
||||
classElements.set( i, entityPropertyData ); //this works since they are in the same order
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2087,10 +2113,9 @@ public final class
|
|||
|
||||
XProperty property = propertyAnnotatedElement.getProperty();
|
||||
if(property.isAnnotationPresent(GeneratedValue.class) &&
|
||||
property.isAnnotationPresent(Id.class))
|
||||
{
|
||||
property.isAnnotationPresent(Id.class) ) {
|
||||
//clone classGenerator and override with local values
|
||||
HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) new HashMap<String, IdGenerator>();
|
||||
HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
|
||||
localGenerators.putAll( buildLocalGenerators( property, mappings ) );
|
||||
|
||||
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
|
||||
|
@ -2647,10 +2672,10 @@ public final class
|
|||
return inheritanceStatePerClass;
|
||||
}
|
||||
|
||||
private static boolean hasIdClassAnnotations(XClass idClass)
|
||||
private static boolean hasAnnotationsOnIdClass(XClass idClass)
|
||||
{
|
||||
if(idClass.getAnnotation(Embeddable.class) != null)
|
||||
return true;
|
||||
// if(idClass.getAnnotation(Embeddable.class) != null)
|
||||
// return true;
|
||||
|
||||
List<XProperty> properties = idClass.getDeclaredProperties( XClass.ACCESS_FIELD );
|
||||
for ( XProperty property : properties ) {
|
||||
|
|
|
@ -65,7 +65,6 @@ import org.hibernate.DuplicateMappingException;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.annotations.AnyMetaDef;
|
||||
import org.hibernate.annotations.Cache;
|
||||
|
@ -158,6 +157,7 @@ public class AnnotationConfiguration extends Configuration {
|
|||
private boolean isDefaultProcessed = false;
|
||||
private boolean isValidatorNotPresentLogged;
|
||||
private Map<XClass,Map<String,PropertyData>> propertiesAnnotatedWithMapsId;
|
||||
private Map<XClass,Map<String,PropertyData>> propertiesAnnotatedWithIdAndToOne;
|
||||
|
||||
public AnnotationConfiguration() {
|
||||
super();
|
||||
|
@ -297,6 +297,7 @@ public class AnnotationConfiguration extends Configuration {
|
|||
setEntityResolver( new EJB3DTDEntityResolver() );
|
||||
anyMetaDefs = new HashMap<String, AnyMetaDef>();
|
||||
propertiesAnnotatedWithMapsId = new HashMap<XClass, Map<String,PropertyData>>();
|
||||
propertiesAnnotatedWithIdAndToOne = new HashMap<XClass, Map<String,PropertyData>>();
|
||||
reflectionManager = new JavaReflectionManager();
|
||||
( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new JPAMetadataProvider() );
|
||||
|
||||
|
@ -1293,6 +1294,20 @@ public class AnnotationConfiguration extends Configuration {
|
|||
map.put( property.getProperty().getAnnotation( MapsId.class ).value(), property );
|
||||
}
|
||||
|
||||
public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName) {
|
||||
final Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne.get( entityType );
|
||||
return map == null ? null : map.get( propertyName );
|
||||
}
|
||||
|
||||
public void addToOneAndIdProperty(XClass entityType, PropertyData property) {
|
||||
Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne.get( entityType );
|
||||
if (map == null) {
|
||||
map = new HashMap<String, PropertyData>();
|
||||
propertiesAnnotatedWithIdAndToOne.put( entityType, map );
|
||||
}
|
||||
map.put( property.getPropertyName(), property );
|
||||
}
|
||||
|
||||
private Boolean useNewGeneratorMappings;
|
||||
|
||||
@SuppressWarnings({ "UnnecessaryUnboxing" })
|
||||
|
|
|
@ -652,7 +652,7 @@ public class BinderHelper {
|
|||
return StringHelper.qualify( holder.getPath(), property.getPropertyName() );
|
||||
}
|
||||
|
||||
static PropertyData getPropertyAnnotatedWithMapsId(boolean isId, PropertyHolder propertyHolder, String propertyName, ExtendedMappings mappings) {
|
||||
static PropertyData getPropertyOverriddenByMapperOrMapsId(boolean isId, PropertyHolder propertyHolder, String propertyName, ExtendedMappings mappings) {
|
||||
final XClass persistentXClass;
|
||||
try {
|
||||
persistentXClass = mappings.getReflectionManager()
|
||||
|
@ -661,8 +661,12 @@ public class BinderHelper {
|
|||
catch ( ClassNotFoundException e ) {
|
||||
throw new AssertionFailure( "PersistentClass name cannot be converted into a Class", e);
|
||||
}
|
||||
String propertyPath = isId ? "" : propertyName;
|
||||
final PropertyData annotatedWithMapsId = mappings.getPropertyAnnotatedWithMapsId( persistentXClass, propertyPath );
|
||||
return annotatedWithMapsId;
|
||||
if ( propertyHolder.isInIdClass() ) {
|
||||
return mappings.getPropertyAnnotatedWithIdAndToOne( persistentXClass, propertyName );
|
||||
}
|
||||
else {
|
||||
String propertyPath = isId ? "" : propertyName;
|
||||
return mappings.getPropertyAnnotatedWithMapsId( persistentXClass, propertyPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,10 @@ import javax.persistence.OneToMany;
|
|||
import javax.persistence.OneToOne;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.annotations.CollectionOfElements;
|
||||
import org.hibernate.annotations.Columns;
|
||||
import org.hibernate.annotations.Formula;
|
||||
import org.hibernate.annotations.JoinColumnsOrFormulas;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.cfg.annotations.EntityBinder;
|
||||
import org.hibernate.cfg.annotations.Nullability;
|
||||
|
@ -183,15 +181,13 @@ class ColumnsBuilder {
|
|||
return joinColumns;
|
||||
}
|
||||
|
||||
Ejb3Column[] overrideColumnFromMapsIdProperty(boolean isId) {
|
||||
Ejb3Column[] overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
|
||||
Ejb3Column[] result = columns;
|
||||
final PropertyData annotatedWithMapsId = BinderHelper.getPropertyAnnotatedWithMapsId( isId, propertyHolder, property.getName(), mappings );
|
||||
final PropertyData annotatedWithMapsId = BinderHelper.getPropertyOverriddenByMapperOrMapsId( isId, propertyHolder, property.getName(), mappings );
|
||||
if ( annotatedWithMapsId != null ) {
|
||||
result = buildExplicitJoinColumns( annotatedWithMapsId.getProperty(), annotatedWithMapsId );
|
||||
if (result == null) {
|
||||
result = buildDefaultJoinColumnsForXToOne( annotatedWithMapsId.getProperty(), annotatedWithMapsId);
|
||||
// throw new UnsupportedOperationException( "Implicit @JoinColumn is not supported on @MapsId properties: "
|
||||
// + annotatedWithMapsId.getDeclaringClass() + " " + annotatedWithMapsId.getPropertyName() );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -188,4 +188,12 @@ public interface ExtendedMappings extends Mappings {
|
|||
* @return True if the new generators should be used, false otherwise.
|
||||
*/
|
||||
public boolean useNewGeneratorMappings();
|
||||
|
||||
/**
|
||||
* Return the property annotated with @ToOne and @Id if any.
|
||||
* Null otherwise
|
||||
*/
|
||||
public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName);
|
||||
|
||||
void addToOneAndIdProperty(XClass entity, PropertyData property);
|
||||
}
|
|
@ -89,4 +89,8 @@ public interface PropertyHolder {
|
|||
String getEntityName();
|
||||
|
||||
Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation);
|
||||
|
||||
boolean isInIdClass();
|
||||
|
||||
void setInIdClass(Boolean isInIdClass);
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ import java.io.Serializable;
|
|||
*/
|
||||
public class DependentId implements Serializable {
|
||||
String name;
|
||||
long empPK; // corresponds to PK type of Employee
|
||||
long emp; // corresponds to PK type of Employee
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package org.hibernate.test.annotations.derivedidentities.e1.a;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.junit.FailureExpected;
|
||||
import org.hibernate.test.annotations.TestCase;
|
||||
import org.hibernate.test.util.SchemaUtil;
|
||||
|
||||
|
@ -10,36 +11,40 @@ import org.hibernate.test.util.SchemaUtil;
|
|||
public class
|
||||
DerivedIdentitySimpleParentIdClassDepTest extends TestCase {
|
||||
|
||||
@FailureExpected( jiraKey = "HHH-4848" )
|
||||
public void testManyToOne() throws Exception {
|
||||
// assertTrue( SchemaUtil.isColumnPresent( "Dependent", "FK", getCfg() ) );
|
||||
// assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "empPK", getCfg() ) );
|
||||
// Employee e = new Employee();
|
||||
// e.empId = 1;
|
||||
// e.empName = "Emmanuel";
|
||||
// Session s = openSession( );
|
||||
// s.getTransaction().begin();
|
||||
// s.persist( e );
|
||||
// Dependent d = new Dependent();
|
||||
// d.emp = e;
|
||||
// d.name = "Doggy";
|
||||
// d.emp = e;
|
||||
// s.persist( d );
|
||||
// s.flush();
|
||||
// s.clear();
|
||||
// DependentId dId = new DependentId();
|
||||
// dId.name = d.name;
|
||||
// dId.empPK = d.emp.empId;
|
||||
// d = (Dependent) s.get( Dependent.class, dId );
|
||||
// assertEquals( e.empId, d.emp.empId );
|
||||
// s.getTransaction().rollback();
|
||||
// s.close();
|
||||
assertTrue( SchemaUtil.isColumnPresent( "Dependent", "emp_empId", getCfg() ) );
|
||||
assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "emp", getCfg() ) );
|
||||
Employee e = new Employee();
|
||||
e.empId = 1;
|
||||
e.empName = "Emmanuel";
|
||||
e.nickname = "Manu";
|
||||
Session s = openSession( );
|
||||
s.getTransaction().begin();
|
||||
s.persist( e );
|
||||
Dependent d = new Dependent();
|
||||
d.emp = e;
|
||||
d.name = "Doggy";
|
||||
d.emp = e;
|
||||
s.persist( d );
|
||||
s.flush();
|
||||
s.clear();
|
||||
DependentId dId = new DependentId();
|
||||
dId.name = d.name;
|
||||
dId.emp = d.emp.empId;
|
||||
d = (Dependent) s.get( Dependent.class, dId );
|
||||
assertEquals( e.empId, d.emp.empId );
|
||||
assertEquals( e.empName, d.emp.empName );
|
||||
assertEquals( e.nickname, d.emp.nickname );
|
||||
s.getTransaction().rollback();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
//Dependent.class,
|
||||
//Employee.class
|
||||
Dependent.class,
|
||||
Employee.class
|
||||
};
|
||||
}
|
||||
}
|
|
@ -11,4 +11,6 @@ public class Employee {
|
|||
@Id
|
||||
long empId;
|
||||
String empName;
|
||||
|
||||
String nickname;
|
||||
}
|
|
@ -33,6 +33,7 @@ import org.hibernate.TransientObjectException;
|
|||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.ForeignKeys;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -95,18 +96,26 @@ public class ForeignGenerator implements IdentifierGenerator, Configurable {
|
|||
public Serializable generate(SessionImplementor sessionImplementor, Object object) {
|
||||
Session session = ( Session ) sessionImplementor;
|
||||
|
||||
Object associatedObject = sessionImplementor.getFactory()
|
||||
.getClassMetadata( entityName )
|
||||
final ClassMetadata classMetadata = sessionImplementor.getFactory()
|
||||
.getClassMetadata( entityName );
|
||||
Object associatedObject = classMetadata
|
||||
.getPropertyValue( object, propertyName, session.getEntityMode() );
|
||||
if ( associatedObject == null ) {
|
||||
throw new IdentifierGenerationException(
|
||||
"attempted to assign id from null one-to-one property [" + getRole() + "]"
|
||||
);
|
||||
}
|
||||
|
||||
EntityType type = (EntityType) sessionImplementor.getFactory()
|
||||
.getClassMetadata( entityName )
|
||||
.getPropertyType( propertyName );
|
||||
|
||||
final Type uncheckedType = classMetadata
|
||||
.getPropertyType( propertyName );
|
||||
EntityType type;
|
||||
if (uncheckedType instanceof EntityType) {
|
||||
type = (EntityType) uncheckedType;
|
||||
}
|
||||
else {
|
||||
//try identifier mapper
|
||||
type = (EntityType) classMetadata.getPropertyType( "_identifierMapper." + propertyName );
|
||||
}
|
||||
|
||||
Serializable id;
|
||||
try {
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyAccessException;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tuple.Instantiator;
|
||||
import org.hibernate.tuple.VersionProperty;
|
||||
import org.hibernate.tuple.StandardProperty;
|
||||
|
@ -45,6 +47,8 @@ import org.hibernate.property.Setter;
|
|||
import org.hibernate.proxy.ProxyFactory;
|
||||
import org.hibernate.type.AbstractComponentType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -70,6 +74,9 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
private final ProxyFactory proxyFactory;
|
||||
private final AbstractComponentType identifierMapperType;
|
||||
|
||||
public Type getIdentifierMapperType() {
|
||||
return identifierMapperType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an appropriate Getter for the given property.
|
||||
|
@ -192,13 +199,27 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
else {
|
||||
ComponentType copier = (ComponentType) entityMetamodel.getIdentifierProperty().getType();
|
||||
id = copier.instantiate( getEntityMode() );
|
||||
copier.setPropertyValues( id, identifierMapperType.getPropertyValues( entity, getEntityMode() ), getEntityMode() );
|
||||
final Object[] propertyValues = identifierMapperType.getPropertyValues( entity, getEntityMode() );
|
||||
Type[] subTypes = identifierMapperType.getSubtypes();
|
||||
Type[] copierSubTypes = copier.getSubtypes();
|
||||
final int length = subTypes.length;
|
||||
for ( int i = 0 ; i < length; i++ ) {
|
||||
//JPA 2 in @IdClass points to the pk of the entity
|
||||
if ( subTypes[i].isAssociationType() && ! copierSubTypes[i].isAssociationType()) {
|
||||
final String associatedEntityName = ( ( EntityType ) subTypes[i] ).getAssociatedEntityName();
|
||||
final EntityPersister entityPersister = getFactory().getEntityPersister(
|
||||
associatedEntityName
|
||||
);
|
||||
propertyValues[i] = entityPersister.getIdentifier( propertyValues[i], getEntityMode() );
|
||||
}
|
||||
}
|
||||
copier.setPropertyValues( id, propertyValues, getEntityMode() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
id = idGetter.get( entity );
|
||||
}
|
||||
}
|
||||
id = idGetter.get( entity );
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return (Serializable) id;
|
||||
|
@ -229,7 +250,18 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
else if ( identifierMapperType != null ) {
|
||||
ComponentType extractor = (ComponentType) entityMetamodel.getIdentifierProperty().getType();
|
||||
ComponentType copier = (ComponentType) identifierMapperType;
|
||||
copier.setPropertyValues( entity, extractor.getPropertyValues( id, getEntityMode() ), getEntityMode() );
|
||||
final Object[] propertyValues = extractor.getPropertyValues( id, getEntityMode() );
|
||||
Type[] subTypes = identifierMapperType.getSubtypes();
|
||||
Type[] copierSubTypes = copier.getSubtypes();
|
||||
final int length = subTypes.length;
|
||||
for ( int i = 0 ; i < length; i++ ) {
|
||||
//JPA 2 in @IdClass points to the pk of the entity
|
||||
if ( subTypes[i].isAssociationType() && ! copierSubTypes[i].isAssociationType() ) {
|
||||
final String associatedEntityName = ( ( EntityType ) subTypes[i] ).getAssociatedEntityName();
|
||||
//FIXME find the entity for the given id (propertyValue[i])
|
||||
}
|
||||
}
|
||||
copier.setPropertyValues( entity, propertyValues, getEntityMode() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,18 +331,27 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
}
|
||||
|
||||
public Object getPropertyValue(Object entity, String propertyPath) throws HibernateException {
|
||||
final int loc = propertyPath.indexOf('.');
|
||||
final String basePropertyName = loc > 0
|
||||
int loc = propertyPath.indexOf('.');
|
||||
String basePropertyName = loc > 0
|
||||
? propertyPath.substring( 0, loc )
|
||||
: propertyPath;
|
||||
final int index = entityMetamodel.getPropertyIndex( basePropertyName );
|
||||
final Object baseValue = getPropertyValue( entity, index );
|
||||
//final int index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
|
||||
Integer index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
|
||||
if (index == null) {
|
||||
propertyPath = "_identifierMapper." + propertyPath;
|
||||
loc = propertyPath.indexOf('.');
|
||||
basePropertyName = loc > 0
|
||||
? propertyPath.substring( 0, loc )
|
||||
: propertyPath;
|
||||
}
|
||||
index = entityMetamodel.getPropertyIndexOrNull( basePropertyName );
|
||||
final Object baseValue = getPropertyValue( entity, index.intValue() );
|
||||
if ( loc > 0 ) {
|
||||
if ( baseValue == null ) {
|
||||
return null;
|
||||
}
|
||||
return getComponentValue(
|
||||
(ComponentType) entityMetamodel.getPropertyTypes()[index],
|
||||
(ComponentType) entityMetamodel.getPropertyTypes()[index.intValue()],
|
||||
baseValue,
|
||||
propertyPath.substring(loc+1)
|
||||
);
|
||||
|
|
|
@ -307,7 +307,13 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier();
|
||||
}
|
||||
else {
|
||||
id = persister.getIdentifier(x, entityMode);
|
||||
final Class mappedClass = persister.getMappedClass( entityMode );
|
||||
if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
|
||||
id = persister.getIdentifier(x, entityMode);
|
||||
}
|
||||
else {
|
||||
id = (Serializable) x;
|
||||
}
|
||||
}
|
||||
return persister.getIdentifierType().getHashCode(id, entityMode, factory);
|
||||
}
|
||||
|
@ -321,13 +327,20 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
return super.isEqual(x, y, entityMode);
|
||||
}
|
||||
|
||||
final Class mappedClass = persister.getMappedClass( entityMode );
|
||||
Serializable xid;
|
||||
if (x instanceof HibernateProxy) {
|
||||
xid = ( (HibernateProxy) x ).getHibernateLazyInitializer()
|
||||
.getIdentifier();
|
||||
}
|
||||
else {
|
||||
xid = persister.getIdentifier(x, entityMode);
|
||||
if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
|
||||
xid = persister.getIdentifier(x, entityMode);
|
||||
}
|
||||
else {
|
||||
//JPA 2 case where @IdClass contains the id and not the associated entity
|
||||
xid = (Serializable) x;
|
||||
}
|
||||
}
|
||||
|
||||
Serializable yid;
|
||||
|
@ -336,7 +349,13 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
.getIdentifier();
|
||||
}
|
||||
else {
|
||||
yid = persister.getIdentifier(y, entityMode);
|
||||
if ( mappedClass.isAssignableFrom( y.getClass() ) ) {
|
||||
yid = persister.getIdentifier(x, entityMode);
|
||||
}
|
||||
else {
|
||||
//JPA 2 case where @IdClass contains the id and not the associated entity
|
||||
yid = (Serializable) y;
|
||||
}
|
||||
}
|
||||
|
||||
return persister.getIdentifierType()
|
||||
|
|
Loading…
Reference in New Issue