From 969b21851f9659e2d6a34d24921731a4b77e0aad Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 19 Dec 2023 16:02:23 +0100 Subject: [PATCH 1/3] HHH-17380 Add test for issue --- .../version/NewEntityWithNullVersion.hbm.xml | 19 ++++++ .../version/NewEntityWithNullVersionTest.java | 68 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersion.hbm.xml create mode 100644 hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersionTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersion.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersion.hbm.xml new file mode 100644 index 000000000000..1877d9c74bd8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersion.hbm.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersionTest.java b/hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersionTest.java new file mode 100644 index 000000000000..677e86962060 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/version/NewEntityWithNullVersionTest.java @@ -0,0 +1,68 @@ +package org.hibernate.test.version; + +import java.io.Serializable; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + + +@TestForIssue(jiraKey = "HHH-17380") +public class NewEntityWithNullVersionTest extends BaseCoreFunctionalTestCase { + + @Override + protected String[] getMappings() { + return new String[] { "NewEntityWithNullVersion.hbm.xml" }; + } + + @Override + protected String getBaseForMappings() { + return super.getBaseForMappings() + "version/"; + } + + @Test + public void testMergeDetachedEntityWithIdentityId() { + UserAttributes item = new UserAttributes(); + item.id = 123L; + item.name = "Abc"; + inTransaction( + session -> { + session.saveOrUpdate( item ); + } + ); + } + + public static class UserAttributes implements Serializable { + + private Long id = 0L; + + private Long version; + + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} + From 26366b425abea81ef698f89646081c82947eb204 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Fri, 3 Nov 2023 09:42:11 +0100 Subject: [PATCH 2/3] HHH-17380 Add test for issue (cherry picked from commit 00340107d44feae6c59db1c02679a5dab0ee5db2) --- .../EntityWithNullVersionAndMapsIdTest.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/version/EntityWithNullVersionAndMapsIdTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/version/EntityWithNullVersionAndMapsIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/version/EntityWithNullVersionAndMapsIdTest.java new file mode 100644 index 000000000000..d70215f7585f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/version/EntityWithNullVersionAndMapsIdTest.java @@ -0,0 +1,91 @@ +package org.hibernate.test.version; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.MapsId; +import javax.persistence.OneToOne; +import javax.persistence.Version; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-17380") +public class EntityWithNullVersionAndMapsIdTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Person.class, + Address.class + }; + } + + @Test + public void testPersistEntityWithMapsId() { + Address address = new Address( "Alex" ); + inTransaction( + session -> { + session.persist( address ); + Person person = new Person( address ); + session.persist( person ); + } + ); + } + + @Entity(name = "Person") + public static class Person { + + @Id + private String name; + + @Version + private Long version; + + private String description; + + @MapsId + @OneToOne + @JoinColumn(name = "name") + private Address address; + + public Person() { + } + + public Person(Address address) { + this.name = address.getName(); + this.address = address; + } + + public String getName() { + return name; + } + + public Address getAddress() { + return address; + } + } + + @Entity(name = "Address") + public static class Address { + @Id + private String name; + + @Version + private Long version; + + private String description; + + public Address() { + } + + public Address(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } +} From e864a3cfff77648e3c92553fcf0034455f415348 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 6 Nov 2023 09:21:09 +0100 Subject: [PATCH 3/3] HHH-17380 Persisting an entity with a non generated id and @MapsId throws PropertyValueException (cherry picked from commit ab861e99fbc9a068e435e96d69d637a3f3e064ea) --- .../entity/AbstractEntityPersister.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 963dfa2419e7..127a9550b717 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -83,6 +83,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.ValueInclusion; +import org.hibernate.id.Assigned; +import org.hibernate.id.ForeignGenerator; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.PostInsertIdentifierGenerator; import org.hibernate.id.PostInsertIdentityPersister; @@ -4731,14 +4733,18 @@ public Boolean isTransient(Object entity, SharedSessionContractImplementor sessi .getUnsavedValue().isUnsaved( version ); if ( isUnsaved != null ) { if ( isUnsaved ) { - final Boolean unsaved = entityMetamodel.getIdentifierProperty() + final IdentifierGenerator identifierGenerator = getIdentifierGenerator(); + if ( identifierGenerator != null && !( identifierGenerator instanceof ForeignGenerator ) + && !( identifierGenerator instanceof Assigned ) ) { + final Boolean unsaved = entityMetamodel.getIdentifierProperty() .getUnsavedValue().isUnsaved( id ); - if ( unsaved != null && !unsaved ) { - throw new PropertyValueException( - "Detached entity with generated id '" + id + "' has an uninitialized version value '" + version + "'", - getEntityName(), - getVersionColumnName() - ); + if ( unsaved != null && !unsaved ) { + throw new PropertyValueException( + "Detached entity with generated id '" + id + "' has an uninitialized version value '" + version + "'", + getEntityName(), + getVersionColumnName() + ); + } } }