diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/collection/ElementCollectionUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/ElementCollectionUpdateTest.java new file mode 100644 index 0000000000..bc34d469bf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/ElementCollectionUpdateTest.java @@ -0,0 +1,124 @@ +package org.hibernate.orm.test.collection; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import org.assertj.core.api.Assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel(annotatedClasses = ElementCollectionUpdateTest.Person.class) +@SessionFactory +@TestForIssue(jiraKey = "HHH-16297") +public class ElementCollectionUpdateTest { + + private Person thePerson; + + @BeforeAll + public void prepare(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Set phones = new HashSet<>( Arrays.asList( "999-999-9999", "111-111-1111", "123-456-7890" ) ); + thePerson = new Person( 7242000, "Claude", phones ); + session.persist( thePerson ); + } ); + } + + @Test + public void removeElementAndAddNewOne(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Person foundPerson = session.find( Person.class, thePerson.getId() ); + Assertions.assertThat( foundPerson ).isNotNull(); + Set phones = foundPerson.getPhones(); + phones.remove( "111-111-1111" ); + phones.add( "000" ); + assertThat( phones ) + .containsExactlyInAnyOrder( "999-999-9999", "123-456-7890", "000" ); + } ); + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + assertThat( person.getPhones() ) + .containsExactlyInAnyOrder( "999-999-9999", "123-456-7890", "000" ); + } ); + + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + person.getPhones().remove( "123-456-7890" ); + } ); + + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + Set phones = person.getPhones(); + assertThat( phones ) + .containsExactlyInAnyOrder( "999-999-9999", "000" ); + phones.add( "111-111-1111" ); + + } ); + + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + Set phones = person.getPhones(); + assertThat( phones ) + .containsExactlyInAnyOrder( "999-999-9999", "000", "111-111-1111" ); + + } ); + } + + @Entity(name = "Person") + @Table(name = "Person") + static class Person { + @Id + private Integer id; + private String name; + + @ElementCollection(fetch = FetchType.EAGER) + private Set phones; + + public Person() { + } + + public Person(Integer id, String name, Collection phones) { + this.id = id; + this.name = name; + this.phones = new HashSet<>( phones ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setPhones(Set phones) { + this.phones = phones; + } + + public Set getPhones() { + return phones; + } + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/collection/OneToManyUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/OneToManyUpdateTest.java new file mode 100644 index 0000000000..7c21f158ff --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/OneToManyUpdateTest.java @@ -0,0 +1,175 @@ +package org.hibernate.orm.test.collection; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import org.assertj.core.api.Assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel( + annotatedClasses = { + OneToManyUpdateTest.Person.class, + OneToManyUpdateTest.Address.class + } +) +@SessionFactory +@TestForIssue(jiraKey = "HHH-16297") +public class OneToManyUpdateTest { + + private static final Integer PERSON_ID = 7242000; + + @BeforeAll + public void prepare(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Address address1 = new Address( 1, "via milano", "Roma" ); + Address address2 = new Address( 2, "via Cartesio", "Milano" ); + Set
addresses = new HashSet<>( Arrays.asList( + address1, + address2 + ) ); + Person person = new Person( PERSON_ID, "Claude", addresses ); + session.persist( address1 ); + session.persist( address2 ); + session.persist( person ); + } ); + } + + @Test + public void removeElementAndAddNewOne(SessionFactoryScope scope) { + Address address3 = new Address( 3, "via Pierce", "Milano" ); + Address address2 = new Address( 2, "via Cartesio", "Milano" ); + scope.inTransaction( session -> { + Person foundPerson = session.find( Person.class, PERSON_ID ); + Assertions.assertThat( foundPerson ).isNotNull(); + Set
addresses = foundPerson.getAddresses(); + Address address1 = new Address( 1, "via milano", "Roma" ); + addresses.remove( address1 ); + addresses.add( address3 ); + session.persist( address3 ); + assertThat( addresses ) + .containsExactlyInAnyOrder( + address3, + address2 + ); + } ); + scope.inTransaction( session -> { + Person person = session.find( Person.class, PERSON_ID ); + Set
addresses = person.getAddresses(); + assertThat( addresses ) + .containsExactlyInAnyOrder( + address3, + address2 + ); + addresses.remove( address2 ); + + } ); + + scope.inTransaction( session -> { + Person person = session.find( Person.class, PERSON_ID ); + Set
addresses = person.getAddresses(); + assertThat( addresses ) + .containsExactlyInAnyOrder( + address3 + ); + } ); + } + + @Entity(name = "Person") + @Table(name = "Person") + static class Person { + @Id + private Integer id; + private String name; + + @OneToMany(fetch = FetchType.EAGER) + private Set
addresses; + + public Person() { + } + + public Person(Integer id, String name, Collection
addresses) { + this.id = id; + this.name = name; + this.addresses = new HashSet<>( addresses ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set
getAddresses() { + return addresses; + } + + public void setAddresses(Set
addresses) { + this.addresses = addresses; + } + + } + + @Entity(name = "Address") + @Table(name = "ADDRESS_TABLE") + public static class Address { + + @Id + private Integer id; + + private String street; + + private String city; + + public Address() { + } + + public Address(Integer id, String street, String city) { + this.id = id; + this.street = street; + this.city = city; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + Address address = (Address) o; + return Objects.equals( street, address.street ) && Objects.equals( city, address.city ); + } + + @Override + public int hashCode() { + return Objects.hash( street, city ); + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/embeddable/EmbeddableAsElementCollectionUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/embeddable/EmbeddableAsElementCollectionUpdateTest.java new file mode 100644 index 0000000000..e999ed76cc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/embeddable/EmbeddableAsElementCollectionUpdateTest.java @@ -0,0 +1,158 @@ +package org.hibernate.orm.test.embeddable; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Basic; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import org.assertj.core.api.Assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel(annotatedClasses = EmbeddableAsElementCollectionUpdateTest.Person.class) +@SessionFactory +@TestForIssue(jiraKey = "HHH-16297") +public class EmbeddableAsElementCollectionUpdateTest { + + private Person thePerson; + + @BeforeAll + public void prepare(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Set
addresses = new HashSet<>( Arrays.asList( + new Address( "via milano", "Roma" ), + new Address( "via Cartesio", "Milano" ) + ) ); + thePerson = new Person( 7242000, "Claude", addresses ); + session.persist( thePerson ); + } ); + } + + @Test + public void removeElementAndAddNewOne(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Person foundPerson = session.find( Person.class, thePerson.getId() ); + Assertions.assertThat( foundPerson ).isNotNull(); + Set
addresses = foundPerson.getAddresses(); + addresses.remove( new Address( "via milano", "Roma" ) ); + addresses.add( new Address( "via Pierce", null ) ); + assertThat( addresses ) + .containsExactlyInAnyOrder( + new Address( "via Pierce", null ), + new Address( "via Cartesio", "Milano" ) + ); + } ); + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + Set
addresses = person.getAddresses(); + assertThat( addresses ) + .containsExactlyInAnyOrder( + new Address( "via Pierce", null ), + new Address( "via Cartesio", "Milano" ) + ); + addresses.remove( new Address( "via Pierce", null ) ); + } ); + + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + Set
addresses = person.getAddresses(); + assertThat( addresses ) + .containsExactlyInAnyOrder( + new Address( "via Cartesio", "Milano" ) + ); + addresses.remove( new Address( "via Pierce", null ) ); + } ); + } + + @Entity(name = "Person") + @Table(name = "Person") + static class Person { + @Id + private Integer id; + private String name; + + @ElementCollection(fetch = FetchType.EAGER) + private Set
addresses; + + public Person() { + } + + public Person(Integer id, String name, Collection
addresses) { + this.id = id; + this.name = name; + this.addresses = new HashSet<>( addresses ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set
getAddresses() { + return addresses; + } + + public void setAddresses(Set
addresses) { + this.addresses = addresses; + } + + } + + @Embeddable + public static class Address { + @Basic(optional = false) + private String street; + private String city; + + public Address() { + } + + public Address(String street, String city) { + this.street = street; + this.city = city; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + Address address = (Address) o; + return Objects.equals( street, address.street ) && Objects.equals( city, address.city ); + } + + @Override + public int hashCode() { + return Objects.hash( street, city ); + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/embeddable/EmbeddableWithNotOprionalAttributeAsElementCollectionUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/embeddable/EmbeddableWithNotOprionalAttributeAsElementCollectionUpdateTest.java new file mode 100644 index 0000000000..cb5c7661b8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/embeddable/EmbeddableWithNotOprionalAttributeAsElementCollectionUpdateTest.java @@ -0,0 +1,147 @@ +package org.hibernate.orm.test.embeddable; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Basic; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import org.assertj.core.api.Assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel(annotatedClasses = EmbeddableWithNotOprionalAttributeAsElementCollectionUpdateTest.Person.class) +@SessionFactory +@TestForIssue(jiraKey = "HHH-16297") +public class EmbeddableWithNotOprionalAttributeAsElementCollectionUpdateTest { + + private Person thePerson; + + @BeforeAll + public void prepare(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Set
addresses = new HashSet<>( Arrays.asList( + new Address( "via milano", "Roma" ), + new Address( "via Cartesio", "Milano" ) + ) ); + thePerson = new Person( 7242000, "Claude", addresses ); + session.persist( thePerson ); + } ); + } + + @Test + public void removeElementAndAddNewOne(SessionFactoryScope scope) { + scope.inTransaction( session -> { + Person foundPerson = session.find( Person.class, thePerson.getId() ); + Assertions.assertThat( foundPerson ).isNotNull(); + Set
addresses = foundPerson.getAddresses(); + addresses.remove( new Address( "via milano", "Roma" ) ); + addresses.add( new Address( "via Pierce", "Milano" ) ); + assertThat( addresses ) + .containsExactlyInAnyOrder( + new Address( "via Pierce", "Milano" ), + new Address( "via Cartesio", "Milano" ) + ); + } ); + scope.inTransaction( session -> { + Person person = session.find( Person.class, thePerson.getId() ); + assertThat( person.getAddresses() ) + .containsExactlyInAnyOrder( + new Address( "via Pierce", "Milano" ), + new Address( "via Cartesio", "Milano" ) + ); + } ); + } + + @Entity(name = "Person") + @Table(name = "Person") + static class Person { + @Id + private Integer id; + private String name; + + @ElementCollection(fetch = FetchType.EAGER) + private Set
addresses; + + public Person() { + } + + public Person(Integer id, String name, Collection
addresses) { + this.id = id; + this.name = name; + this.addresses = new HashSet<>( addresses ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set
getAddresses() { + return addresses; + } + + public void setAddresses(Set
addresses) { + this.addresses = addresses; + } + + } + + @Embeddable + public static class Address { + @Basic(optional = false) + private String street; + @Basic(optional = false) + private String city; + + public Address() { + } + + public Address(String street, String city) { + this.street = street; + this.city = city; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + Address address = (Address) o; + return Objects.equals( street, address.street ) && Objects.equals( city, address.city ); + } + + @Override + public int hashCode() { + return Objects.hash( street, city ); + } + } +}