diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/manytoone/EntityWithManyToOneSelfReferenceTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/manytoone/EntityWithManyToOneSelfReferenceTest.java index 5d6480c03a..36edc0fa08 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/manytoone/EntityWithManyToOneSelfReferenceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/manytoone/EntityWithManyToOneSelfReferenceTest.java @@ -8,6 +8,9 @@ package org.hibernate.orm.test.sql.exec.manytoone; import java.util.List; +import org.hibernate.Hibernate; +import org.hibernate.stat.spi.StatisticsImplementor; + import org.hibernate.testing.orm.domain.gambit.EntityWithManyToOneSelfReference; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.FailureExpected; @@ -19,8 +22,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; /** * @author Steve Ebersole @@ -65,48 +71,125 @@ public class EntityWithManyToOneSelfReferenceTest { } @Test - public void testHqlSelect(SessionFactoryScope scope) { + public void testHqlSelectImplicitJoin(SessionFactoryScope scope) { + StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); scope.inTransaction( session -> { final EntityWithManyToOneSelfReference queryResult = session.createQuery( "select e from EntityWithManyToOneSelfReference e where e.other.name = 'first'", EntityWithManyToOneSelfReference.class ).uniqueResult(); - assertThat( queryResult.getName(), equalTo( "second" ) ); + + assertThat( statistics.getPrepareStatementCount(), is( 2L ) ); + assertThat( queryResult.getName(), is( "second" ) ); + + EntityWithManyToOneSelfReference other = queryResult.getOther(); + assertTrue( Hibernate.isInitialized( other ) ); + assertThat( other.getName(), is( "first" ) ); + + assertThat( statistics.getPrepareStatementCount(), is( 2L ) ); } ); - } @Test - @FailureExpected public void testGetEntity(SessionFactoryScope scope) { - - + StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); scope.inTransaction( session -> { final EntityWithManyToOneSelfReference loaded = session.get( EntityWithManyToOneSelfReference.class, 2 ); - assert loaded != null; - assertThat( loaded.getName(), equalTo( "second" ) ); - assert loaded.getOther() != null; - assertThat( loaded.getOther().getName(), equalTo( "first" ) ); + + assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); + + assertThat( loaded, notNullValue() ); + assertThat( loaded.getName(), is( "second" ) ); + + EntityWithManyToOneSelfReference other = loaded.getOther(); + assertTrue( Hibernate.isInitialized( other ) ); + assertThat( other.getName(), is( "first" ) ); + + assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); } ); + statistics.clear(); scope.inTransaction( session -> { final EntityWithManyToOneSelfReference loaded = session.get( EntityWithManyToOneSelfReference.class, 1 ); - assert loaded != null; - assertThat( loaded.getName(), equalTo( "first" ) ); - assertThat( loaded.getOther(), nullValue() ); + assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); + assertThat( loaded, notNullValue() ); + assertThat( loaded.getName(), is( "first" ) ); + + EntityWithManyToOneSelfReference other = loaded.getOther(); + assertTrue( Hibernate.isInitialized( other ) ); + assertThat( other, nullValue() ); } ); + } + + @Test + public void testHqlSelectField(SessionFactoryScope scope) { + StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); + scope.inTransaction( + session -> { + final String value = session.createQuery( + "select e.name from EntityWithManyToOneSelfReference e where e.other.name = 'first'", + String.class + ).uniqueResult(); + assertThat( value, equalTo( "second" ) ); + assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); + } + ); + } + + @Test + public void testHqlSelectWithJoin(SessionFactoryScope scope) { + StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); + scope.inTransaction( + session -> { + final EntityWithManyToOneSelfReference result = session.createQuery( + "select e from EntityWithManyToOneSelfReference e join e.other o where o.name = 'first'", + EntityWithManyToOneSelfReference.class + ).uniqueResult(); + assertThat( result.getName(), equalTo( "second" ) ); + assertThat( statistics.getPrepareStatementCount(), is( 2L ) ); + + assertTrue( Hibernate.isInitialized( result.getOther() ) ); + } + ); + } + + @Test + public void testHqlSelectWithFetchJoin(SessionFactoryScope scope) { + StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); + statistics.clear(); + scope.inTransaction( + session -> { + final EntityWithManyToOneSelfReference result = session.createQuery( + "select e from EntityWithManyToOneSelfReference e join fetch e.other k where k.name = 'first'", + EntityWithManyToOneSelfReference.class + ).uniqueResult(); + assertThat( result.getName(), equalTo( "second" ) ); + assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); + + assertTrue( Hibernate.isInitialized( result.getOther() ) ); + } + ); + } + + @Test + @FailureExpected + public void testGetByMultipleIds(SessionFactoryScope scope) { scope.inTransaction( session -> { @@ -133,18 +216,5 @@ public class EntityWithManyToOneSelfReferenceTest { assertThat( loaded.getOther().getName(), equalTo( "first" ) ); } ); - - // todo (6.0) : the restriction here uses the wrong table alias... - scope.inTransaction( - session -> { - final String value = session.createQuery( - "select e.name from EntityWithManyToOneSelfReference e where e.other.name = 'first'", - String.class - ).uniqueResult(); - assertThat( value, equalTo( "second" ) ); - } - ); - - } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithLazyOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithLazyOneToOneTest.java new file mode 100644 index 0000000000..d4477b4eff --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithLazyOneToOneTest.java @@ -0,0 +1,150 @@ +/* + * 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.orm.test.sql.exec.onetoone; + +import java.util.Calendar; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest; +import org.hibernate.testing.orm.domain.gambit.EntityWithLazyOneToOne; +import org.hibernate.testing.orm.domain.gambit.SimpleEntity; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.hamcrest.CoreMatchers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +/** + * @author Andrea Boriero + */ +public class EntityWithLazyOneToOneTest extends SessionFactoryBasedFunctionalTest { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + EntityWithLazyOneToOne.class, + SimpleEntity.class + }; + } + + @BeforeEach + public void setUp() { + EntityWithLazyOneToOne entity = new EntityWithLazyOneToOne( 1, "first", Integer.MAX_VALUE ); + + SimpleEntity other = new SimpleEntity( + 2, + Calendar.getInstance().getTime(), + null, + Integer.MAX_VALUE, + Long.MAX_VALUE, + null + ); + + entity.setOther( other ); + + inTransaction( session -> { + session.save( other ); + session.save( entity ); + } ); + } + + @AfterEach + public void tearDown() { + inTransaction( session -> { + deleteAll(); + } ); + } + + @Test + public void testGet() { + inTransaction( + session -> { + final EntityWithLazyOneToOne loaded = session.get( EntityWithLazyOneToOne.class, 1 ); + assert loaded != null; + assertThat( loaded.getName(), equalTo( "first" ) ); + assertFalse( + Hibernate.isInitialized( loaded.getOther() ), + "The lazy association should not be initialized" + ); + + SimpleEntity loadedOther = loaded.getOther(); + assert loadedOther != null; + assertThat( loaded.getOther().getId(), equalTo( 2 ) ); + assertFalse( + Hibernate.isInitialized( loaded.getOther() ), + "getId() should not trigger the lazy association initialization" + + ); + + loadedOther.getSomeDate(); + assertTrue( + Hibernate.isInitialized( loaded.getOther() ), + "The lazy association should be initialized" + ); + + } + ); + + inTransaction( + session -> { + final SimpleEntity loaded = session.get( SimpleEntity.class, 2 ); + assert loaded != null; + assertThat( loaded.getSomeInteger(), equalTo( Integer.MAX_VALUE ) ); + } + ); + } + + @Test + public void testHqlSelect() { + + inTransaction( + session -> { + final String value = session.createQuery( + "select e.name from EntityWithLazyOneToOne e where e.other.id = 2", + String.class + ).uniqueResult(); + assertThat( value, equalTo( "first" ) ); + } + ); + } + + private void deleteAll() { + + inTransaction( + session -> { + final EntityWithLazyOneToOne loaded = session.get( EntityWithLazyOneToOne.class, 1 ); + assert loaded != null; + assert loaded.getOther() != null; + session.remove( loaded ); + } + ); + + inTransaction( + session -> { + final EntityWithLazyOneToOne notfound = session.find( EntityWithLazyOneToOne.class, 1 ); + assertThat( notfound, CoreMatchers.nullValue() ); + } + ); + + inTransaction( + session -> { + final SimpleEntity simpleEntity = session.find( SimpleEntity.class, 2 ); + assertThat( simpleEntity, notNullValue() ); + session.remove( simpleEntity ); + } + ); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneJoinTableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneJoinTableTest.java new file mode 100644 index 0000000000..c26b4b36f6 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneJoinTableTest.java @@ -0,0 +1,140 @@ +/* + * 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.orm.test.sql.exec.onetoone; + +import java.util.Calendar; + +import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest; +import org.hibernate.testing.orm.domain.gambit.EntityWithOneToOneJoinTable; +import org.hibernate.testing.orm.domain.gambit.SimpleEntity; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Andrea Boriero + */ +public class EntityWithOneToOneJoinTableTest extends SessionFactoryBasedFunctionalTest { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + EntityWithOneToOneJoinTable.class, + SimpleEntity.class + }; + } + + @AfterEach + public void tearDown() { + inTransaction( + session -> { + final EntityWithOneToOneJoinTable loaded = session.get( EntityWithOneToOneJoinTable.class, 1 ); + session.delete( loaded ); + session.delete( loaded.getOther() ); + } + ); + } + + @Test + public void testOperations() { + EntityWithOneToOneJoinTable entity = new EntityWithOneToOneJoinTable( 1, "first", Integer.MAX_VALUE ); + + SimpleEntity other = new SimpleEntity( + 2, + Calendar.getInstance().getTime(), + null, + Integer.MAX_VALUE, + Long.MAX_VALUE, + null + ); + + entity.setOther( other ); + + inTransaction( session -> {session.save( other );} ); + inTransaction( session -> {session.save( entity );} ); + + inTransaction( + session -> { + final EntityWithOneToOneJoinTable loaded = session.get( EntityWithOneToOneJoinTable.class, 1 ); + assert loaded != null; + assertThat( loaded.getName(), equalTo( "first" ) ); + assert loaded.getOther() != null; + assertThat( loaded.getOther().getId(), equalTo( 2 ) ); + } + ); + + inTransaction( + session -> { + final SimpleEntity loaded = session.get( SimpleEntity.class, 2 ); + assert loaded != null; + assertThat( loaded.getSomeInteger(), equalTo( Integer.MAX_VALUE ) ); + } + ); + + inTransaction( + session -> { + final String value = session.createQuery( + "select e.name from EntityWithOneToOneJoinTable e where e.other.id = 2", + String.class + ).uniqueResult(); + assertThat( value, equalTo( "first" ) ); + } + ); + } + + @Test + public void testUpdate() { + EntityWithOneToOneJoinTable entity = new EntityWithOneToOneJoinTable( 1, "first", Integer.MAX_VALUE ); + + SimpleEntity other = new SimpleEntity( + 2, + Calendar.getInstance().getTime(), + null, + Integer.MAX_VALUE, + Long.MAX_VALUE, + null + ); + + entity.setOther( other ); + + inTransaction( + session -> { + session.save( other ); + session.save( entity ); + } + ); + + SimpleEntity anOther = new SimpleEntity( + 3, + Calendar.getInstance().getTime(), + null, + Integer.MIN_VALUE, + Long.MAX_VALUE, + null + ); + + inTransaction( + session -> { + EntityWithOneToOneJoinTable loaded = session.get( EntityWithOneToOneJoinTable.class, 1 ); + session.save( anOther ); + loaded.setOther( anOther ); + } + ); + + inTransaction( + session -> { + EntityWithOneToOneJoinTable loaded = session.get( EntityWithOneToOneJoinTable.class, 1 ); + SimpleEntity loadedOther = loaded.getOther(); + assertThat( loadedOther, notNullValue() ); + assertThat( loadedOther.getId(), equalTo( 3 ) ); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneSharingPrimaryKeyTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneSharingPrimaryKeyTest.java new file mode 100644 index 0000000000..0dd65dadce --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneSharingPrimaryKeyTest.java @@ -0,0 +1,97 @@ +/* + * 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.orm.test.sql.exec.onetoone; + +import java.util.Calendar; + +import org.hibernate.testing.orm.domain.gambit.EntityWithOneToOneSharingPrimaryKey; +import org.hibernate.testing.orm.domain.gambit.SimpleEntity; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.FailureExpected; +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Andrea Boriero + */ +@DomainModel( + annotatedClasses = { + EntityWithOneToOneSharingPrimaryKey.class, + SimpleEntity.class + } +) +@ServiceRegistry +@SessionFactory(generateStatistics = true) +@FailureExpected +public class EntityWithOneToOneSharingPrimaryKeyTest { + + @Test + public void testOperations(SessionFactoryScope scope) { + + SimpleEntity other = new SimpleEntity( + 2, + Calendar.getInstance().getTime(), + null, + Integer.MAX_VALUE, + Long.MAX_VALUE, + null + ); + + EntityWithOneToOneSharingPrimaryKey entity = new EntityWithOneToOneSharingPrimaryKey( + other.getId(), + "first", + Integer.MAX_VALUE + ); + + entity.setOther( other ); + + scope.inTransaction( + + session -> { + session.save( other ); + session.save( entity ); + } ); + + scope.inTransaction( + session -> { + final EntityWithOneToOneSharingPrimaryKey loaded = session.get( + EntityWithOneToOneSharingPrimaryKey.class, + 2 + ); + assert loaded != null; + assertThat( loaded.getName(), equalTo( "first" ) ); + assert loaded.getOther() != null; + assertThat( loaded.getOther().getId(), equalTo( 2 ) ); + } + ); + + scope.inTransaction( + session -> { + final SimpleEntity loaded = session.get( + SimpleEntity.class, + 2 + ); + assert loaded != null; + } + ); + + scope.inTransaction( + session -> { + final String value = session.createQuery( + "select e.name from EntityWithOneToOneSharingPrimaryKey e where e.other.id = 2", + String.class + ).uniqueResult(); + assertThat( value, equalTo( "first" ) ); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneTest.java new file mode 100644 index 0000000000..b6c7bd398e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/EntityWithOneToOneTest.java @@ -0,0 +1,189 @@ +/* + * 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.orm.test.sql.exec.onetoone; + +import java.util.Calendar; + +import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest; +import org.hibernate.testing.orm.domain.gambit.EntityWithOneToOne; +import org.hibernate.testing.orm.domain.gambit.SimpleEntity; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.hamcrest.CoreMatchers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Andrea Boriero + */ +public class EntityWithOneToOneTest extends SessionFactoryBasedFunctionalTest { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + EntityWithOneToOne.class, + SimpleEntity.class + }; + } + + @BeforeEach + public void setUp() { + EntityWithOneToOne entity = new EntityWithOneToOne( 1, "first", Integer.MAX_VALUE ); + + SimpleEntity other = new SimpleEntity( + 2, + Calendar.getInstance().getTime(), + null, + Integer.MAX_VALUE, + Long.MAX_VALUE, + null + ); + + entity.setOther( other ); + + inTransaction( session -> { + session.save( other ); + session.save( entity ); + } ); + } + + @AfterEach + public void tearDown() { + deleteAll(); + } + + @Test + public void testGet() { + inTransaction( + session -> { + final EntityWithOneToOne loaded = session.get( EntityWithOneToOne.class, 1 ); + assert loaded != null; + assertThat( loaded.getName(), equalTo( "first" ) ); + assert loaded.getOther() != null; + assertThat( loaded.getOther().getId(), equalTo( 2 ) ); + } + ); + + inTransaction( + session -> { + final SimpleEntity loaded = session.get( SimpleEntity.class, 2 ); + assert loaded != null; + assertThat( loaded.getSomeInteger(), equalTo( Integer.MAX_VALUE ) ); + } + ); + } + + @Test + public void testUpdate(){ + SimpleEntity other = new SimpleEntity( + 3, + Calendar.getInstance().getTime(), + null, + Integer.MIN_VALUE, + Long.MIN_VALUE, + null + ); + + inTransaction( + session -> { + final EntityWithOneToOne loaded = session.get( EntityWithOneToOne.class, 1 ); + assert loaded != null; + assertThat( loaded.getName(), equalTo( "first" ) ); + assert loaded.getOther() != null; + assertThat( loaded.getOther().getId(), equalTo( 2 ) ); + session.delete( loaded.getOther() ); + loaded.setOther( other ); + session.save( other ); + } + ); + + inTransaction( + session -> { + final EntityWithOneToOne loaded = session.get( EntityWithOneToOne.class, 1 ); + assert loaded != null; + assertThat( loaded.getName(), equalTo( "first" ) ); + assert loaded.getOther() != null; + assertThat( loaded.getOther().getId(), equalTo( 3 ) ); + } + ); + + } + + @Test + public void testQueryParentAttribute2() { + inTransaction( + session -> { + final String value = session.createQuery( + "select e.name from EntityWithOneToOne e where e.id = 1", + String.class + ).uniqueResult(); + assertThat( value, equalTo( "first" ) ); + } + ); + } + + @Test + public void testQueryParentAttribute3() { + inTransaction( + session -> { + final EntityWithOneToOne value = session.createQuery( + "select e from EntityWithOneToOne e where e.id = 1", + EntityWithOneToOne.class + ).uniqueResult(); + assertThat( value.getName(), equalTo( "first" ) ); + } + ); + } + + @Test + public void testQueryParentAttribute() { + inTransaction( + session -> { + final String value = session.createQuery( + "select e.name from EntityWithOneToOne e where e.other.id = 2", + String.class + ).uniqueResult(); + assertThat( value, equalTo( "first" ) ); + } + ); + } + + @Test + public void testQueryParent() { + inTransaction( + session -> { + final EntityWithOneToOne value = session.createQuery( + "select e from EntityWithOneToOne e where e.other.id = 2", + EntityWithOneToOne.class + ).uniqueResult(); + assertThat( value.getName(), equalTo( "first" ) ); + } + ); + } + + private void deleteAll() { + inTransaction( + session -> { + final EntityWithOneToOne loaded = session.get( EntityWithOneToOne.class, 1 ); + assert loaded != null; + assert loaded.getOther() != null; + session.remove( loaded ); + session.remove( loaded.getOther() ); + } + ); + + inTransaction( + session -> { + final EntityWithOneToOne notfound = session.find( EntityWithOneToOne.class, 1 ); + assertThat( notfound, CoreMatchers.nullValue() ); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/OneToOneWithDerivedIdentityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/OneToOneWithDerivedIdentityTest.java new file mode 100644 index 0000000000..abdc5cd378 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/OneToOneWithDerivedIdentityTest.java @@ -0,0 +1,120 @@ +/* + * 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.orm.test.crud.onetoone; + +import javax.persistence.Basic; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToOne; + +import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Andrea Boriero + */ +@Disabled("non-aggregated composite-id not yet implemented") +public class OneToOneWithDerivedIdentityTest extends SessionFactoryBasedFunctionalTest { + + private static final Integer PERSON_ID = 1; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Person.class, + PersonInfo.class + }; + } + + @Test + public void testGet() { + inTransaction( + session -> { + + Person p = new Person(); + p.setId( 0 ); + p.setName( "Alfio" ); + PersonInfo pi = new PersonInfo(); + pi.setId( p ); + pi.setInfo( "Some information" ); + session.persist( p ); + session.persist( pi ); + + } ); + + inTransaction( + session -> { + Person person = session.get( Person.class, PERSON_ID ); + assertEquals( person.getName(), "Alfio" ); + } ); + } + + @Entity + public static class Person { + @Id + private Integer id; + + @Basic + private String name; + + @OneToOne(mappedBy = "id") + private PersonInfo personInfo; + + public Integer getId() { + return this.id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public PersonInfo getPersonInfo() { + return this.personInfo; + } + + public void setPersonInfo(PersonInfo personInfo) { + this.personInfo = personInfo; + } + } + + @Entity + public class PersonInfo { + @Id + @OneToOne + private Person id; + + @Basic + private String info; + + public Person getId() { + return this.id; + } + + public void setId(Person id) { + this.id = id; + } + + public String getInfo() { + return this.info; + } + + public void setInfo(String info) { + this.info = info; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneJoinTableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneJoinTableTest.java new file mode 100644 index 0000000000..ab4c27b885 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneJoinTableTest.java @@ -0,0 +1,334 @@ +/* + * 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.orm.test.sql.exec.onetoone.bidirectional; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.FailureExpected; +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.hamcrest.CoreMatchers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Andrea Boriero + */ +@DomainModel( + annotatedClasses = { + EntityWithBidirectionalOneToOneJoinTableTest.Parent.class, + EntityWithBidirectionalOneToOneJoinTableTest.Child.class, + EntityWithBidirectionalOneToOneJoinTableTest.Child2.class, + } +) +@ServiceRegistry +@SessionFactory(generateStatistics = true) +@FailureExpected +public class EntityWithBidirectionalOneToOneJoinTableTest { + + @BeforeEach + public void setUp(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent parent = new Parent( 1, "Hibernate" ); + Child child = new Child( 2, parent ); + child.setName( "Acme" ); + Child2 child2 = new Child2( 3, parent ); + child2.setName( "Fab" ); + session.save( parent ); + session.save( child ); + session.save( child2 ); + } ); + } + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from Parent" ).executeUpdate(); + session.createQuery( "delete from Child" ).executeUpdate(); + session.createQuery( "delete from Child2" ).executeUpdate(); + } ); + } + + @Test + public void testGetParent(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + final Parent parent = session.get( Parent.class, 1 ); + Child child = parent.getChild(); + assertThat( child, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child ), + "The child eager OneToOne association is not initialized" + ); + assertThat( child.getName(), equalTo( "Acme" ) ); + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + + + Child2 child2 = parent.getChild2(); + assertThat( child2, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child2 ), + "The child2 eager OneToOne association is not initialized" + ); + assertThat( child2.getName(), equalTo( "Fab" ) ); + assertThat( child2.getParent(), CoreMatchers.notNullValue() ); + + } ); + } + + @Test + public void testGetChild(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final Child child = session.get( Child.class, 2 ); + Parent parent = child.getParent(); + assertThat( parent, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( parent ), + "The parent eager OneToOne association is not initialized" + ); + assertThat( parent.getDescription(), CoreMatchers.notNullValue() ); + + Child child1 = parent.getChild(); + assertThat( child1, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child1 ), + "The child eager OneToOne association is not initialized" + ); + + Child2 child2 = parent.getChild2(); + assertThat( child2, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child2 ), + "The child2 eager OneToOne association is not initialized" + + ); + assertThat( child2.getParent(), CoreMatchers.notNullValue() ); + } ); + } + + @Test + public void testHqlSelectChild(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + final String queryString = "SELECT c FROM Child c JOIN c.parent d WHERE d.id = :id"; + final Child child = session.createQuery( queryString, Child.class ) + .setParameter( "id", 1 ) + .getSingleResult(); + + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + + String description = child.getParent().getDescription(); + assertThat( description, CoreMatchers.notNullValue() ); + } + ); + } + + @Test + public void testHqlSelectParent(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + final Parent parent = session.createQuery( + "SELECT p FROM Parent p JOIN p.child WHERE p.id = :id", + Parent.class + ) + .setParameter( "id", 1 ) + .getSingleResult(); + + Child child = parent.getChild(); + assertThat( child, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child ), + "the child have to be initialized" + ); + String name = child.getName(); + assertThat( name, CoreMatchers.notNullValue() ); + } + + ); + + scope.inTransaction( + session -> { + final Parent parent = session.createQuery( + "SELECT p FROM Parent p JOIN p.child WHERE p.id = :id", + Parent.class + ) + .setParameter( "id", 1 ) + .getSingleResult(); + + Child child = parent.getChild(); + assertThat( child, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child ), + "The child have to be initialized" + ); + String name = child.getName(); + assertThat( name, CoreMatchers.notNullValue() ); + } + + ); + } + + @Entity(name = "Parent") + @Table(name = "PARENT") + public static class Parent { + private Integer id; + + private String description; + private Child child; + private Child2 child2; + + Parent() { + } + + public Parent(Integer id, String description) { + this.id = id; + this.description = description; + } + + @Id + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @OneToOne + @JoinTable(name = "PARENT_CHILD", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id")) + public Child getChild() { + return child; + } + + public void setChild(Child other) { + this.child = other; + } + + @OneToOne + @JoinTable(name = "PARENT_CHILD2", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id")) + public Child2 getChild2() { + return child2; + } + + public void setChild2(Child2 child2) { + this.child2 = child2; + } + } + + @Entity(name = "Child") + @Table(name = "CHILD") + public static class Child { + private Integer id; + + private String name; + private Parent parent; + + Child() { + } + + Child(Integer id, Parent parent) { + this.id = id; + this.parent = parent; + this.parent.setChild( this ); + } + + @Id + 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; + } + + @OneToOne(mappedBy = "child") + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Child2") + @Table(name = "CHILD2") + public static class Child2 { + private Integer id; + + private String name; + private Parent parent; + + Child2() { + } + + Child2(Integer id, Parent child) { + this.id = id; + this.parent = child; + this.parent.setChild2( this ); + } + + @Id + 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; + } + + @OneToOne(mappedBy = "child2") + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java new file mode 100644 index 0000000000..bd8c899160 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalOneToOneTest.java @@ -0,0 +1,410 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.sql.exec.onetoone.bidirectional; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +import org.hibernate.Hibernate; +import org.hibernate.boot.MetadataSources; +import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest; +import org.hibernate.testing.orm.junit.FailureExpected; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import org.hamcrest.CoreMatchers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Chris Cranford + */ +@Disabled(value = "Composite FK not yet supported") +public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunctionalTest { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class, + Child2.class, + }; + } + + @BeforeEach + public void setUp() { + inTransaction( session -> { + Parent parent = new Parent( 1, "Hibernate ORM" ); + Child child = new Child( 2, parent ); + child.setName( "Acme" ); + Child2 child2 = new Child2( 3, parent ); + child2.setName( "Fab" ); + session.save( parent ); + session.save( child ); + session.save( child2 ); + } ); + } + + @AfterEach + public void tearDown() { + inTransaction( session -> { + session.createQuery( "delete from Child" ).executeUpdate(); + session.createQuery( "delete from Child2" ).executeUpdate(); + session.createQuery( "delete from Parent" ).executeUpdate(); + } ); + } + + @Test + public void testGetParent() { + inTransaction( session -> { + final Parent parent = session.get( Parent.class, 1 ); + Child child = parent.getChild(); + assertThat( child, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child ), + "The child eager OneToOne association is not initialized" + ); + assertThat( child.getName(), CoreMatchers.notNullValue() ); + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + + Child2 child2 = parent.getChild2(); + assertThat( child2, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child2 ), + "The child2 eager OneToOne association is not initialized" + ); + assertThat( child2.getName(), equalTo( "Fab" ) ); + assertThat( child2.getParent(), CoreMatchers.notNullValue() ); + + } ); + } + + @Test + public void testGetParent2() { + inTransaction( session -> { + Parent parent = new Parent( 4, "Hibernate OGM" ); + Child child = new Child( 5, parent ); + child.setName( "Acme2" ); + + Child2 child2 = new Child2( 6, parent ); + child2.setName( "Fab2" ); + + child2.setParent2( parent ); + + session.save( parent ); + session.save( child ); + session.save( child2 ); + } ); + + inTransaction( session -> { + final Parent parent = session.get( Parent.class, 4 ); + Child child = parent.getChild(); + assertThat( child, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child ), + "The child eager OneToOne association is not initialized" + ); + assertThat( child.getName(), CoreMatchers.notNullValue() ); + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + + Child2 child2 = parent.getChild2(); + assertThat( child2, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child2 ), + "The child2 eager OneToOne association is not initialized" + ); + assertThat( child2.getName(), equalTo( "Fab2" ) ); + assertThat( child2.getParent(), CoreMatchers.notNullValue() ); + assertThat( child2.getParent().getDescription(), equalTo( "Hibernate OGM" ) ); + + Parent parent2 = child2.getParent2(); + assertThat( parent2, CoreMatchers.notNullValue() ); + assertThat( parent2.getDescription(), equalTo( "Hibernate OGM" ) ); + assertThat( parent2.getChild(), CoreMatchers.notNullValue() ); + + } ); + } + + @Test + public void testGetParent3() { + inTransaction( session -> { + + Parent parent = new Parent( 4, "Hibernate Search" ); + Child child = new Child( 5, parent ); + child.setName( "Acme2" ); + Child2 child2 = new Child2( 7, parent ); + child2.setName( "Fab2" ); + + Parent parent2 = new Parent( 6, "Hibernate OGM" ); + child2.setParent2( parent2 ); + + Child child1 = new Child( 8, parent2 ); + + session.save( parent ); + session.save( parent2 ); + session.save( child ); + session.save( child1 ); + session.save( child2 ); + } ); + + inTransaction( session -> { + final Parent parent = session.get( Parent.class, 4 ); + assertThat( parent.getDescription(), equalTo( "Hibernate Search" ) ); + + Child child = parent.getChild(); + assertThat( child, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child ), + "The child eager OneToOne association is not initialized" + ); + assertThat( child.getName(), CoreMatchers.notNullValue() ); + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + + Child2 child2 = parent.getChild2(); + assertThat( child2, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child2 ), + "The child2 eager OneToOne association is not initialized" + ); + assertThat( child2.getName(), equalTo( "Fab2" ) ); + assertThat( child2.getParent(), CoreMatchers.notNullValue() ); + assertThat( child2.getParent().getDescription(), equalTo( "Hibernate Search" ) ); + + Parent parent2 = child2.getParent2(); + assertThat( parent2, CoreMatchers.notNullValue() ); + assertThat( parent2.getDescription(), equalTo( "Hibernate OGM" ) ); + assertThat( parent2.getChild(), CoreMatchers.notNullValue() ); + + } ); + } + + @Test + public void testGetChild() { + inTransaction( session -> { + final Child child = session.get( Child.class, 2 ); + Parent parent = child.getParent(); + assertTrue( + Hibernate.isInitialized( parent ), + "The parent eager OneToOne association is not initialized" + ); + assertThat( parent, CoreMatchers.notNullValue() ); + assertThat( parent.getDescription(), CoreMatchers.notNullValue() ); + Child child1 = parent.getChild(); + assertThat( child1, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child1 ), + "The child eager OneToOne association is not initialized" + ); + Child2 child2 = parent.getChild2(); + assertThat( child2, CoreMatchers.notNullValue() ); + assertTrue( + Hibernate.isInitialized( child2 ), + "The child2 eager OneToOne association is not initialized" + ); + assertThat( child2.getParent(), CoreMatchers.notNullValue() ); + } ); + } + + @Test + public void testHqlSelectParent() { + inTransaction( + session -> { + final Parent parent = session.createQuery( + "SELECT p FROM Parent p JOIN p.child WHERE p.id = :id", + Parent.class + ) + .setParameter( "id", 1 ) + .getSingleResult(); + + assertThat( parent.getChild(), CoreMatchers.notNullValue() ); + String name = parent.getChild().getName(); + assertThat( name, CoreMatchers.notNullValue() ); + } + ); + } + + @Test + public void testHqlSelectChild() { + inTransaction( + session -> { + final String queryString = "SELECT c FROM Child c JOIN c.parent d WHERE d.id = :id"; + final Child child = session.createQuery( queryString, Child.class ) + .setParameter( "id", 1 ) + .getSingleResult(); + + assertThat( child.getParent(), CoreMatchers.notNullValue() ); + + String description = child.getParent().getDescription(); + assertThat( description, CoreMatchers.notNullValue() ); + } + ); + } + + @Entity(name = "Parent") + public static class Parent { + @Id + private Integer id; + private String description; + @OneToOne(mappedBy = "parent") + private Child child; + @OneToOne(mappedBy = "parent") + private Child2 child2; + + Parent() { + } + + public Parent(Integer id, String description) { + this.id = id; + this.description = description; + } + + Parent(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Child getChild() { + return child; + } + + public void setChild(Child child) { + this.child = child; + } + + public Child2 getChild2() { + return child2; + } + + public void setChild2(Child2 child2) { + this.child2 = child2; + } + + } + + @Entity(name = "Child") + public static class Child { + @Id + private Integer id; + private String name; + @OneToOne + private Parent parent; + + Child() { + + } + + Child(Integer id, Parent parent) { + this.id = id; + this.parent = parent; + this.parent.setChild( this ); + } + + 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 Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Child2") + @Table(name = "CHILD2") + public static class Child2 { + @Id + private Integer id; + + private String name; + + @OneToOne + private Parent parent; + + @OneToOne + private Parent parent2; + + Child2() { + } + + Child2(Integer id, Parent parent) { + this.id = id; + this.parent = parent; + this.parent.setChild2( this ); + } + + + 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 Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + + public Parent getParent2() { + return parent2; + } + + public void setParent2(Parent parent) { + this.parent2 = parent; + } + } +}