From 3906816ee2625987796feb587ca374a55c3374ae Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 19 Dec 2016 16:35:48 -0600 Subject: [PATCH] HHH-11274 - EntityManagerFactoryImpl.getIdentifier uses deprecated version of getIdentifier --- .../jpa/internal/PersistenceUnitUtilImpl.java | 33 +++- .../tuple/entity/AbstractEntityTuplizer.java | 144 ++++++++++++------ .../factory/puUtil/GetIdentifierTest.java | 70 +++++++++ .../jpa/test/factory/puUtil/LegacyEntity.java | 77 ++++++++++ .../test/factory/puUtil/LegacyEntityPk.java | 54 +++++++ .../jpa/test/factory/puUtil/ModernEntity.java | 63 ++++++++ .../factory/puUtil/NestedLegacyEntity.java | 76 +++++++++ .../factory/puUtil/NestedLegacyEntityPk.java | 54 +++++++ .../CompositeIdDerivedIdWithIdClassTest.java | 7 + 9 files changed, 525 insertions(+), 53 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/GetIdentifierTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntityPk.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/ModernEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntityPk.java diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java index 0adcb28e7d..378a783d1b 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java @@ -11,9 +11,11 @@ import javax.persistence.PersistenceUnitUtil; import javax.persistence.spi.LoadState; import org.hibernate.Hibernate; +import org.hibernate.engine.spi.ManagedEntity; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.jpa.internal.util.PersistenceUtilHelper; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.proxy.HibernateProxy; import org.jboss.logging.Logger; @@ -59,12 +61,31 @@ public class PersistenceUnitUtilImpl implements PersistenceUnitUtil, Serializabl @Override public Object getIdentifier(Object entity) { - final Class entityClass = Hibernate.getClass( entity ); - final EntityPersister persister = sessionFactory.getMetamodel().entityPersister( entityClass ); - if ( persister == null ) { - throw new IllegalArgumentException( entityClass + " is not an entity" ); + if ( entity == null ) { + throw new IllegalArgumentException( "Passed entity cannot be null" ); + } + + if ( entity instanceof HibernateProxy ) { + final HibernateProxy proxy = (HibernateProxy) entity; + return proxy.getHibernateLazyInitializer().getIdentifier(); + } + else if ( entity instanceof ManagedEntity ) { + final ManagedEntity enhancedEntity = (ManagedEntity) entity; + return enhancedEntity.$$_hibernate_getEntityEntry().getId(); + } + else { + log.debugf( + "javax.persistence.PersistenceUnitUtil.getIdentifier is only intended to work with enhanced entities " + + "(although Hibernate also adapts this support to its proxies); " + + "however the passed entity was not enhanced (nor a proxy).. may not be able to read identifier" + ); + final Class entityClass = Hibernate.getClass( entity ); + final EntityPersister persister = sessionFactory.getMetamodel().entityPersister( entityClass ); + if ( persister == null ) { + throw new IllegalArgumentException( entityClass + " is not an entity" ); + } + //TODO does that work for @IdClass? + return persister.getIdentifier( entity ); } - //TODO does that work for @IdClass? - return persister.getIdentifier( entity ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java index b9578fb10e..c6e76d968a 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java @@ -7,11 +7,13 @@ package org.hibernate.tuple.entity; import java.io.Serializable; +import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.hibernate.EntityMode; +import org.hibernate.EntityNameResolver; import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; @@ -175,6 +177,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { else { identifierMapperType = (CompositeType) mapper.getType(); mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller( + getFactory(), (ComponentType) entityMetamodel.getIdentifierProperty().getType(), (ComponentType) identifierMapperType ); @@ -275,6 +278,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { private final MappedIdentifierValueMarshaller mappedIdentifierValueMarshaller; private static MappedIdentifierValueMarshaller buildMappedIdentifierValueMarshaller( + SessionFactoryImplementor sessionFactory, ComponentType mappedIdClassComponentType, ComponentType virtualIdComponent) { // so basically at this point we know we have a "mapped" composite identifier @@ -301,8 +305,9 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { return wereAllEquivalent ? new NormalMappedIdentifierValueMarshaller( virtualIdComponent, mappedIdClassComponentType ) : new IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller( - virtualIdComponent, - mappedIdClassComponentType + sessionFactory, + virtualIdComponent, + mappedIdClassComponentType ); } @@ -337,12 +342,15 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { private static class IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller implements MappedIdentifierValueMarshaller { + private final SessionFactoryImplementor sessionFactory; private final ComponentType virtualIdComponent; private final ComponentType mappedIdentifierType; private IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller( + SessionFactoryImplementor sessionFactory, ComponentType virtualIdComponent, ComponentType mappedIdentifierType) { + this.sessionFactory = sessionFactory; this.virtualIdComponent = virtualIdComponent; this.mappedIdentifierType = mappedIdentifierType; } @@ -353,25 +361,18 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity, entityMode ); final Type[] subTypes = virtualIdComponent.getSubtypes(); final Type[] copierSubTypes = mappedIdentifierType.getSubtypes(); - final Iterable persistEventListeners = persistEventListeners( session ); final int length = subTypes.length; for ( int i = 0; i < length; i++ ) { if ( propertyValues[i] == null ) { throw new HibernateException( "No part of a composite identifier may be null" ); } //JPA 2 @MapsId + @IdClass points to the pk of the entity - if ( subTypes[i].isAssociationType() && !copierSubTypes[i].isAssociationType() ) { - // we need a session to handle this use case - if ( session == null ) { - throw new AssertionError( - "Deprecated version of getIdentifier (no session) was used but session was required" - ); - } + if ( subTypes[i].isAssociationType() && !copierSubTypes[i].isAssociationType() ) { propertyValues[i] = determineEntityIdPersistIfNecessary( propertyValues[i], (AssociationType) subTypes[i], session, - persistEventListeners + sessionFactory ); } } @@ -396,7 +397,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { final String associatedEntityName = ( (EntityType) virtualPropertyType ).getAssociatedEntityName(); final EntityKey entityKey = session.generateEntityKey( (Serializable) extractedValues[i], - session.getFactory().getMetamodel().entityPersister( associatedEntityName ) + sessionFactory.getMetamodel().entityPersister( associatedEntityName ) ); // it is conceivable there is a proxy, so check that first Object association = persistenceContext.getProxy( entityKey ); @@ -415,6 +416,9 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { } private static Iterable persistEventListeners(SharedSessionContractImplementor session) { + if ( session == null ) { + return Collections.emptyList(); + } return session .getFactory() .getServiceRegistry() @@ -427,62 +431,108 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { Object entity, AssociationType associationType, SharedSessionContractImplementor session, - Iterable persistEventListeners) { + SessionFactoryImplementor sessionFactory) { + if ( entity == null ) { + return null; + } + + // NOTE : persist if necessary for proper merge support (HHH-11328) + // but only allow persist if a Session is passed (HHH-11274) + if ( HibernateProxy.class.isInstance( entity ) ) { // entity is a proxy, so we know it is not transient; just return ID from proxy return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); } - else { - EntityEntry pcEntry = session.getPersistenceContext().getEntry( entity ); + + if ( session != null ) { + final EntityEntry pcEntry = session.getPersistenceContext().getEntry( entity ); if ( pcEntry != null ) { // entity managed; return ID. return pcEntry.getId(); } - else { - final EntityPersister persister = session.getEntityPersister( - associationType.getAssociatedEntityName( session.getFactory() ), - entity - ); - Serializable entityId = persister.getIdentifier( entity, session ); - if ( entityId == null ) { - // entity is transient with no ID; we need to persist the entity to get the ID. - entityId = persistTransientEntity( entity, session, persistEventListeners ); + } + + final EntityPersister persister = resolveEntityPersister( + entity, + associationType, + session, + sessionFactory + ); + + Serializable entityId = persister.getIdentifier( entity, session ); + + if ( entityId == null ) { + if ( session != null ) { + // if we have a session, then follow the HHH-11328 requirements + entityId = persistTransientEntity( entity, session ); + } + // otherwise just let it be null HHH-11274 + } + else { + if ( session != null ) { + // if the entity is in the process of being merged, it may be stored in the + // PC already, but doesn't have an EntityEntry yet. If this is the case, + // then don't persist even if it is transient because doing so can lead + // to having 2 entities in the PC with the same ID (HHH-11328). + final EntityKey entityKey = session.generateEntityKey( entityId, persister ); + if ( session.getPersistenceContext().getEntity( entityKey ) == null && + ForeignKeys.isTransient( + persister.getEntityName(), + entity, + null, + session + ) ) { + // entity is transient and it is not in the PersistenceContext. + // entity needs to be persisted. + persistTransientEntity( entity, session ); } - else { - // entity has an ID. - final EntityKey entityKey = session.generateEntityKey( entityId, persister ); - // if the entity is in the process of being merged, it may be stored in the - // PC already, but doesn't have an EntityEntry yet. If this is the case, - // then don't persist even if it is transient because doing so can lead - // to having 2 entities in the PC with the same ID (HHH-11328). - if ( session.getPersistenceContext().getEntity( entityKey ) == null && - ForeignKeys.isTransient( - persister.getEntityName(), - entity, - null, - session - ) ) { - // entity is transient and it is not in the PersistenceContext. - // entity needs to be persisted. - persistTransientEntity( entity, session, persistEventListeners ); - } - } - return entityId; } } + return entityId; + } + + private static EntityPersister resolveEntityPersister( + Object entity, + AssociationType associationType, + SharedSessionContractImplementor session, + SessionFactoryImplementor sessionFactory) { + assert sessionFactory != null; + + if ( session != null ) { + return session.getEntityPersister( + associationType.getAssociatedEntityName( session.getFactory() ), + entity + ); + } + + String entityName = null; + for ( EntityNameResolver entityNameResolver : sessionFactory.getMetamodel().getEntityNameResolvers() ) { + entityName = entityNameResolver.resolveEntityName( entity ); + if ( entityName != null ) { + break; + } + } + if ( entityName == null ) { + // old fall-back + entityName = entity.getClass().getName(); + } + + return sessionFactory.getMetamodel().entityPersister( entityName ); } private static Serializable persistTransientEntity( Object entity, - SharedSessionContractImplementor session, - Iterable persistEventListeners) { + SharedSessionContractImplementor session) { + assert session != null; + LOG.debug( "Performing implicit derived identity cascade" ); final PersistEvent event = new PersistEvent( null, entity, (EventSource) session ); - for ( PersistEventListener listener : persistEventListeners ) { + + for ( PersistEventListener listener : persistEventListeners( session ) ) { listener.onPersist( event ); } final EntityEntry pcEntry = session.getPersistenceContext().getEntry( entity ); diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/GetIdentifierTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/GetIdentifierTest.java new file mode 100644 index 0000000000..b2a06b8003 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/GetIdentifierTest.java @@ -0,0 +1,70 @@ +/* + * 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.jpa.test.factory.puUtil; + +import java.io.Serializable; +import javax.persistence.EntityManager; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Steve Ebersole + */ +public class GetIdentifierTest extends BaseEntityManagerFunctionalTestCase { + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + LegacyEntity.class, + ModernEntity.class, + NestedLegacyEntity.class + }; + } + + @Before + public void createData() { + + } + + @After + public void dropData() { + + } + + @Test + public void getIdentifierTest() throws Exception { + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + + // This gives a NullPointerException right now. Look at HHH-10623 when this issue is fixed + Serializable nestedLegacyEntityId = (Serializable) entityManager.getEntityManagerFactory() + .getPersistenceUnitUtil().getIdentifier(createExisitingNestedLegacyEntity()); + + entityManager.getTransaction().commit(); + entityManager.close(); + } + + private NestedLegacyEntity createExisitingNestedLegacyEntity() { + + ModernEntity modernEntity = new ModernEntity(); + modernEntity.setFoo(2); + + LegacyEntity legacyEntity = new LegacyEntity(); + legacyEntity.setPrimitivePk1(1); + legacyEntity.setPrimitivePk2(2); + legacyEntity.setFoo("Foo"); + + NestedLegacyEntity nestedLegacyEntity = new NestedLegacyEntity(); + nestedLegacyEntity.setModernEntity(modernEntity); + nestedLegacyEntity.setLegacyEntity(legacyEntity); + + return nestedLegacyEntity; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntity.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntity.java new file mode 100644 index 0000000000..06f302e9a9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntity.java @@ -0,0 +1,77 @@ +/* + * 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.jpa.test.factory.puUtil; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +@Entity(name = "LegacyEntity") +@IdClass(LegacyEntityPk.class) +public class LegacyEntity { + + @Id + private int primitivePk1; + + @Id + private int primitivePk2; + + private String foo; + + public LegacyEntity() {} + + public int getPrimitivePk1() { + return primitivePk1; + } + + public void setPrimitivePk1(int primitivePk1) { + this.primitivePk1 = primitivePk1; + } + + public int getPrimitivePk2() { + return primitivePk2; + } + + public void setPrimitivePk2(int primitivePk2) { + this.primitivePk2 = primitivePk2; + } + + public String getFoo() { + return foo; + } + + public void setFoo(String foo) { + this.foo = foo; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LegacyEntity that = (LegacyEntity) o; + + if (primitivePk1 != that.primitivePk1) return false; + return primitivePk2 == that.primitivePk2; + + } + + @Override + public int hashCode() { + int result = primitivePk1; + result = 31 * result + primitivePk2; + return result; + } + + @Override + public String toString() { + return "LegacyEntity{" + + "primitivePk1=" + primitivePk1 + + ", primitivePk2=" + primitivePk2 + + '}'; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntityPk.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntityPk.java new file mode 100644 index 0000000000..f3307fc589 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/LegacyEntityPk.java @@ -0,0 +1,54 @@ +/* + * 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.jpa.test.factory.puUtil; + +import java.io.Serializable; + +public class LegacyEntityPk implements Serializable { + + private int primitivePk1; + + private int primitivePk2; + + public LegacyEntityPk() { + } + + public int getPrimitivePk1() { + return primitivePk1; + } + + public void setPrimitivePk1(int primitivePk1) { + this.primitivePk1 = primitivePk1; + } + + public int getPrimitivePk2() { + return primitivePk2; + } + + public void setPrimitivePk2(int primitivePk2) { + this.primitivePk2 = primitivePk2; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LegacyEntityPk that = (LegacyEntityPk) o; + + if (primitivePk1 != that.primitivePk1) return false; + return primitivePk2 == that.primitivePk2; + + } + + @Override + public int hashCode() { + int result = primitivePk1; + result = 31 * result + primitivePk2; + return result; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/ModernEntity.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/ModernEntity.java new file mode 100644 index 0000000000..2da6f5b429 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/ModernEntity.java @@ -0,0 +1,63 @@ +/* + * 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.jpa.test.factory.puUtil; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity(name = "ModernEntity") +public class ModernEntity { + + @Id + @GeneratedValue + private int id; + + private int foo; + + public ModernEntity() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getFoo() { + return foo; + } + + public void setFoo(int foo) { + this.foo = foo; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ModernEntity that = (ModernEntity) o; + + return id == that.id; + + } + + @Override + public int hashCode() { + return id; + } + + @Override + public String toString() { + return "ModernEntity{" + + "id=" + id + + '}'; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntity.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntity.java new file mode 100644 index 0000000000..977c83266a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntity.java @@ -0,0 +1,76 @@ +/* + * 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.jpa.test.factory.puUtil; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.JoinColumn; +import javax.persistence.JoinColumns; +import javax.persistence.ManyToOne; + +@Entity(name = "NestedLegacyEntity") +@IdClass(NestedLegacyEntityPk.class) +public class NestedLegacyEntity { + + @Id + @ManyToOne + @JoinColumns({@JoinColumn(name = "legacyFk1", referencedColumnName = "primitivePk1"), + @JoinColumn(name = "legacyFk2", referencedColumnName = "primitivePk2")}) + private LegacyEntity legacyEntity; + + @Id + @ManyToOne + @JoinColumn(name = "modernFk", referencedColumnName = "id") + private ModernEntity modernEntity; + + public NestedLegacyEntity() { + } + + public LegacyEntity getLegacyEntity() { + return legacyEntity; + } + + public void setLegacyEntity(LegacyEntity legacyEntity) { + this.legacyEntity = legacyEntity; + } + + public ModernEntity getModernEntity() { + return modernEntity; + } + + public void setModernEntity(ModernEntity modernEntity) { + this.modernEntity = modernEntity; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + NestedLegacyEntity that = (NestedLegacyEntity) o; + + if (legacyEntity != null ? !legacyEntity.equals(that.legacyEntity) : that.legacyEntity != null) return false; + return modernEntity != null ? modernEntity.equals(that.modernEntity) : that.modernEntity == null; + + } + + @Override + public int hashCode() { + int result = legacyEntity != null ? legacyEntity.hashCode() : 0; + result = 31 * result + (modernEntity != null ? modernEntity.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "NestedLegacyEntity{" + + "legacyEntity=" + legacyEntity + + ", modernEntity=" + modernEntity + + '}'; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntityPk.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntityPk.java new file mode 100644 index 0000000000..b6afbbe1de --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/jpa/test/factory/puUtil/NestedLegacyEntityPk.java @@ -0,0 +1,54 @@ +/* + * 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.jpa.test.factory.puUtil; + +import java.io.Serializable; + +public class NestedLegacyEntityPk implements Serializable { + + private LegacyEntityPk legacyEntity; + + private int modernEntity; + + public NestedLegacyEntityPk() { + } + + public LegacyEntityPk getLegacyEntity() { + return legacyEntity; + } + + public void setLegacyEntity(LegacyEntityPk legacyEntity) { + this.legacyEntity = legacyEntity; + } + + public int getModernEntity() { + return modernEntity; + } + + public void setModernEntity(int modernEntity) { + this.modernEntity = modernEntity; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + NestedLegacyEntityPk that = (NestedLegacyEntityPk) o; + + if (modernEntity != that.modernEntity) return false; + return legacyEntity != null ? legacyEntity.equals(that.legacyEntity) : that.legacyEntity == null; + + } + + @Override + public int hashCode() { + int result = legacyEntity != null ? legacyEntity.hashCode() : 0; + result = 31 * result + modernEntity; + return result; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/CompositeIdDerivedIdWithIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/CompositeIdDerivedIdWithIdClassTest.java index f1c85aaacc..f28566b877 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/CompositeIdDerivedIdWithIdClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/bidirectional/CompositeIdDerivedIdWithIdClassTest.java @@ -23,6 +23,8 @@ import org.junit.After; import org.junit.Test; import org.hibernate.Session; +import org.hibernate.jpa.internal.PersistenceUnitUtilImpl; + import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -53,6 +55,9 @@ public class CompositeIdDerivedIdWithIdClassTest extends BaseCoreFunctionalTestC ShoppingCart transientCart = new ShoppingCart( "cart1" ); transientCart.addLineItem( new LineItem( 0, "description2", transientCart ) ); + // assertion for HHH-11274 - checking for exception + final Object identifier = new PersistenceUnitUtilImpl( sessionFactory() ).getIdentifier( transientCart.getLineItems().get( 0 ) ); + // merge ID with transient many-to-one Session s = openSession(); s.getTransaction().begin(); @@ -63,6 +68,8 @@ public class CompositeIdDerivedIdWithIdClassTest extends BaseCoreFunctionalTestC s = openSession(); s.getTransaction().begin(); ShoppingCart updatedCart = s.get( ShoppingCart.class, "cart1" ); + // assertion for HHH-11274 - checking for exception + new PersistenceUnitUtilImpl( sessionFactory() ).getIdentifier( transientCart.getLineItems().get( 0 ) ); assertEquals( 1, updatedCart.getLineItems().size() ); assertEquals( "description2", updatedCart.getLineItems().get( 0 ).getDescription() ); s.getTransaction().commit();