Add more tests

This commit is contained in:
Andrea Boriero 2020-05-28 15:04:13 +01:00
parent 2bf36075a4
commit 511d4d55cd
34 changed files with 2184 additions and 445 deletions

View File

@ -4,7 +4,8 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.cid.keymanytoone; package org.hibernate.orm.test.annotations.cid.keymanytoone;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -27,14 +28,15 @@ public class Card implements Serializable {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "primaryKey.card") @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "primaryKey.card")
private Set<CardField> fields; private Set<CardField> fields;
String model;
Card() {
fields = new HashSet<>();
}
public Card(String id) { public Card(String id) {
this(); this();
this.id = id; this.id = id;
}
Card() {
fields = new HashSet<CardField>();
} }
public String getId() { public String getId() {
@ -46,7 +48,7 @@ public class Card implements Serializable {
} }
public void addField(Card card, Key key) { public void addField(Card card, Key key) {
fields.add(new CardField(card, key)); fields.add(new CardField( card, key));
} }
public Set<CardField> getFields() { public Set<CardField> getFields() {
@ -56,4 +58,12 @@ public class Card implements Serializable {
public void setFields(Set<CardField> fields) { public void setFields(Set<CardField> fields) {
this.fields = fields; this.fields = fields;
} }
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
} }

View File

@ -4,7 +4,8 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.cid.keymanytoone; package org.hibernate.orm.test.annotations.cid.keymanytoone;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.EmbeddedId; import javax.persistence.EmbeddedId;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -21,7 +22,7 @@ public class CardField implements Serializable {
private PrimaryKey primaryKey; private PrimaryKey primaryKey;
CardField(Card card, Key key) { CardField(Card card, Key key) {
this.primaryKey = new PrimaryKey(card, key); this.primaryKey = new PrimaryKey( card, key);
} }
CardField() { CardField() {

View File

@ -0,0 +1,94 @@
/*
* 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.annotations.cid.keymanytoone;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
Card.class, CardField.class, Key.class
})
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EagerKeyManyToOneTest {
public static final String CARD_ID = "cardId";
public static final String CARD_MODEL = "Gran Torino";
public static final String KEY_ID = "keyId";
public static final String KEY_SERIAL = "123";
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Card card = new Card( CARD_ID );
card.setModel( CARD_MODEL );
Key key = new Key( KEY_ID, KEY_SERIAL );
card.addField( card, key );
session.persist( key );
session.persist( card );
}
);
}
@AfterEach
public void cleanUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from CardField" ).executeUpdate();
session.createQuery( "delete from Card" ).executeUpdate();
session.createQuery( "delete from Key" ).executeUpdate();
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-4147")
public void testLoadEntityWithEagerFetchingToKeyManyToOneReferenceBackToSelf(SessionFactoryScope scope) {
// based on the core testsuite test of same name in org.hibernate.orm.test.keymanytoone.bidir.component.EagerKeyManyToOneTest
// meant to test against regression relating to http://opensource.atlassian.com/projects/hibernate/browse/HHH-2277
// and http://opensource.atlassian.com/projects/hibernate/browse/HHH-4147
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
try {
Card card = session.get( Card.class, CARD_ID );
assertEquals( 1, card.getFields().size() );
assertEquals( CARD_MODEL, card.getModel() );
CardField cf = card.getFields().iterator().next();
PrimaryKey primaryKey = cf.getPrimaryKey();
assertSame( card, primaryKey.getCard() );
assertEquals( KEY_ID, primaryKey.getKey().getId() );
assertEquals( KEY_SERIAL, primaryKey.getKey().getSerial() );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
}
catch (StackOverflowError soe) {
fail( "eager + key-many-to-one caused stack-overflow in annotations" );
}
}
);
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.annotations.cid.keymanytoone;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
@Entity
@Table(name="`key`")
public class Key implements Serializable {
@Id
private String id;
private String serial;
public Key(String id, String serial) {
this.id = id;
this.serial = serial;
}
Key() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
}

View File

@ -4,7 +4,8 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.cid.keymanytoone; package org.hibernate.orm.test.annotations.cid.keymanytoone;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Embeddable; import javax.persistence.Embeddable;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;

View File

@ -0,0 +1,46 @@
/*
* 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.annotations.cid.keymanytoone.association;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* @author Andrea Boriero
*/
@Entity
public class Card {
@Id
private String id;
@ManyToOne
private CardField field;
Card(){
}
public Card(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public CardField getField() {
return field;
}
public void setField(CardField field) {
this.field = field;
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.annotations.cid.keymanytoone.association;
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
@Entity
public class CardField implements Serializable {
@EmbeddedId
private PrimaryKey primaryKey;
CardField(Card card, Key key) {
this.primaryKey = new PrimaryKey( card, key);
}
CardField() {
}
public PrimaryKey getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(PrimaryKey primaryKey) {
this.primaryKey = primaryKey;
}
}

View File

@ -0,0 +1,82 @@
/*
* 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.annotations.cid.keymanytoone.association;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
Card.class, CardField.class, Key.class
})
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EagerKeyManyToOneTest {
public static final String CARD_ID = "cardId";
public static final String KEY_ID = "keyId";
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Card card = new Card( CARD_ID );
Key key = new Key( KEY_ID );
CardField field = new CardField( card, key );
card.setField( field );
session.persist( key );
session.persist( card );
session.persist( field );
}
);
}
@AfterEach
public void cleanUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Card card = session.get( Card.class, CARD_ID );
session.delete( card.getField());
session.delete( card );
}
);
}
@Test
public void testLoadEntityWithEagerFetchingToKeyManyToOneReferenceBackToSelf(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
try {
Card card = session.get( Card.class, CARD_ID );
CardField cf = card.getField();
assertSame( card, cf.getPrimaryKey().getCard() );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 3 );
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
}
catch (StackOverflowError soe) {
fail( "eager + key-many-to-one caused stack-overflow in annotations" );
}
}
);
}
}

View File

@ -4,7 +4,8 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.cid.keymanytoone; package org.hibernate.orm.test.annotations.cid.keymanytoone.association;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;

View File

@ -0,0 +1,49 @@
/*
* 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.annotations.cid.keymanytoone.association;
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
@Embeddable
public class PrimaryKey implements Serializable {
@ManyToOne(optional = false)
private Card card;
@ManyToOne(optional = false)
private Key key;
public PrimaryKey(Card card, Key key) {
this.card = card;
this.key = key;
}
PrimaryKey() {
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
}

View File

@ -0,0 +1,196 @@
/*
* 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.annotations.embedded;
import java.util.List;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hibernate.orm.test.annotations.embedded.EmbeddableBiDirectionalSelfReferenceTest.EntityTest;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityTest.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EmbeddableBiDirectionalSelfReferenceTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 1 );
EmbeddableTest embeddable = new EmbeddableTest();
embeddable.setEntity( entity );
embeddable.setStringField( "Fab" );
entity.setEmbeddedAttribute( embeddable );
session.save( entity );
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
List<EntityTest> results = session.createQuery( "from EntityTest" ).list();
results.forEach(
result -> session.delete( result )
);
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 1 );
EmbeddableTest embeddedAttribute = entity.getEmbeddedAttribute();
assertThat( embeddedAttribute, notNullValue() );
assertThat( embeddedAttribute.getStringField(), is( "Fab" ) );
assertSame( entity, embeddedAttribute.getEntity() );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
}
);
}
@Test
public void testGet2(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 2 );
EntityTest entity2 = new EntityTest( 3 );
EntityTest entity3 = new EntityTest( 4 );
EmbeddableTest embeddable = new EmbeddableTest();
embeddable.setEntity( entity2 );
embeddable.setStringField( "Acme" );
entity.setEmbeddedAttribute( embeddable );
EmbeddableTest embeddable2 = new EmbeddableTest();
embeddable2.setEntity( entity3 );
embeddable2.setStringField( "Acme2" );
entity2.setEmbeddedAttribute( embeddable2 );
session.save( entity );
session.save( entity2 );
session.save( entity3 );
}
);
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 2 );
EmbeddableTest embeddedAttribute = entity.getEmbeddedAttribute();
assertThat( embeddedAttribute, notNullValue() );
assertThat( embeddedAttribute.getStringField(), is( "Acme" ) );
EntityTest entity2 = embeddedAttribute.getEntity();
assertThat( entity2, notNullValue() );
assertThat( entity2.getId(), is( 3 ) );
EmbeddableTest embeddedAttribute2 = entity2.getEmbeddedAttribute();
assertThat( embeddedAttribute2.getStringField(), is( "Acme2" ) );
EntityTest entity3 = embeddedAttribute2.getEntity();
assertThat( entity3.getId(), is( 4 ) );
assertThat( entity3.getEmbeddedAttribute(), nullValue() );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 1 );
}
);
}
@Entity(name = "EntityTest")
public static class EntityTest {
@Id
private Integer id;
@Embedded
private EmbeddableTest embeddedAttribute;
public EntityTest() {
}
public EntityTest(int id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EmbeddableTest getEmbeddedAttribute() {
return embeddedAttribute;
}
public void setEmbeddedAttribute(EmbeddableTest embeddedAttribute) {
this.embeddedAttribute = embeddedAttribute;
}
}
@Embeddable
public static class EmbeddableTest {
private String stringField;
@ManyToOne
private EntityTest entity;
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
public EntityTest getEntity() {
return entity;
}
public void setEntity(EntityTest entity) {
this.entity = entity;
}
}
}

View File

@ -0,0 +1,181 @@
/*
* 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.annotations.embedded;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EmbeddableWithManyToOneCircularityTest.EntityTest.class,
EmbeddableWithManyToOneCircularityTest.EntityTest2.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EmbeddableWithManyToOneCircularityTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 1 );
EntityTest2 entityTest2 = new EntityTest2( 2 );
EmbeddableTest embeddable = new EmbeddableTest();
embeddable.setEntity( entity );
embeddable.setStringField( "Fab" );
entityTest2.setEmbeddedAttribute( embeddable );
entity.setEntity2( entityTest2 );
session.save( entity );
session.save( entityTest2 );
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "from EntityTest", EntityTest.class ).list().forEach(
entityTest -> {
session.delete( entityTest );
}
);
session.createQuery( "from EntityTest2", EntityTest2.class ).list().forEach(
entityTest -> {
session.delete( entityTest );
}
);
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 1 );
EntityTest2 entity2 = entity.getEntity2();
assertSame( entity, entity2.getEmbeddedAttribute().getEntity() );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
}
);
}
@Entity(name = "EntityTest")
public static class EntityTest {
@Id
private Integer id;
@ManyToOne
private EntityTest2 entity2;
public EntityTest() {
}
public EntityTest(int id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityTest2 getEntity2() {
return entity2;
}
public void setEntity2(EntityTest2 entity2) {
this.entity2 = entity2;
}
}
@Entity(name = "EntityTest2")
public static class EntityTest2 {
@Id
private Integer id;
@Embedded
private EmbeddableTest embeddedAttribute;
public EntityTest2() {
}
public EntityTest2(int id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EmbeddableTest getEmbeddedAttribute() {
return embeddedAttribute;
}
public void setEmbeddedAttribute(EmbeddableTest embeddedAttribute) {
this.embeddedAttribute = embeddedAttribute;
}
}
@Embeddable
public static class EmbeddableTest {
private String stringField;
@OneToOne(mappedBy = "entity2")
private EntityTest entity;
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
public EntityTest getEntity() {
return entity;
}
public void setEntity(EntityTest entity) {
this.entity = entity;
}
}
}

View File

@ -0,0 +1,260 @@
/*
* 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.annotations.embedded;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EmbeddableWithManyToOneTest.EntityTest.class,
EmbeddableWithManyToOneTest.EntityTest2.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EmbeddableWithManyToOneTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 1 );
EntityTest2 entityTest2 = new EntityTest2( 2 );
EmbeddableTest embeddable = new EmbeddableTest();
embeddable.setEntity( entity );
embeddable.setStringField( "Fab" );
entityTest2.setEmbeddedAttribute( embeddable );
entity.setEntity2( entityTest2 );
session.save( entity );
session.save( entityTest2 );
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "from EntityTest", EntityTest.class ).list().forEach(
entityTest -> {
session.delete( entityTest );
}
);
session.createQuery( "from EntityTest2", EntityTest2.class ).list().forEach(
entityTest -> {
session.delete( entityTest );
}
);
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 1 );
EntityTest2 entity2 = entity.getEntity2();
assertSame( entity2.getEmbeddedAttribute().getEntity(), entity );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
}
);
}
@Test
public void testGet2(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 3 );
EntityTest2 entityTest2 = new EntityTest2( 4 );
EntityTest entity3 = new EntityTest( 5 );
EmbeddableTest embeddable = new EmbeddableTest();
embeddable.setEntity( entity3 );
embeddable.setStringField( "Fab" );
entityTest2.setEmbeddedAttribute( embeddable );
entity.setEntity2( entityTest2 );
session.save( entity );
session.save( entity3 );
session.save( entityTest2 );
}
);
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 3 );
EntityTest2 entity2 = entity.getEntity2();
EntityTest entity3 = entity2.getEmbeddedAttribute().getEntity();
assertThat( entity3.getId(), is( 5 ) );
assertThat( entity3.getEntity2(), nullValue() );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
}
);
}
@Test
public void testGet3(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 3 );
EntityTest2 entityTest = new EntityTest2( 4 );
EntityTest entity3 = new EntityTest( 5 );
EntityTest2 entityTest2 = new EntityTest2( 6 );
entity3.setEntity2( entityTest2 );
EmbeddableTest embeddable = new EmbeddableTest();
embeddable.setEntity( entity3 );
embeddable.setStringField( "Fab" );
entityTest.setEmbeddedAttribute( embeddable );
entity.setEntity2( entityTest );
session.save( entity );
session.save( entity3 );
session.save( entityTest );
session.save( entityTest2 );
}
);
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 3 );
EntityTest2 entity2 = entity.getEntity2();
EntityTest entity3 = entity2.getEmbeddedAttribute().getEntity();
assertThat( entity3.getId(), is( 5 ) );
assertThat( entity3.getEntity2().getId(), is( 6 ) );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
}
);
}
@Entity(name = "EntityTest")
public static class EntityTest {
@Id
private Integer id;
private String description;
@ManyToOne
private EntityTest2 entity2;
public EntityTest() {
}
public EntityTest(int id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityTest2 getEntity2() {
return entity2;
}
public void setEntity2(EntityTest2 entity2) {
this.entity2 = entity2;
}
}
@Entity(name = "EntityTest2")
public static class EntityTest2 {
@Id
private Integer id;
@Embedded
private EmbeddableTest embeddedAttribute;
public EntityTest2() {
}
public EntityTest2(int id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EmbeddableTest getEmbeddedAttribute() {
return embeddedAttribute;
}
public void setEmbeddedAttribute(EmbeddableTest embeddedAttribute) {
this.embeddedAttribute = embeddedAttribute;
}
}
@Embeddable
public static class EmbeddableTest {
private String stringField;
@ManyToOne
private EntityTest entity;
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
public EntityTest getEntity() {
return entity;
}
public void setEntity(EntityTest entity) {
this.entity = entity;
}
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.orm.test.cascade;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.persistence.OneToMany;
public class A public class A
{ {

View File

@ -30,6 +30,7 @@ import javax.persistence.Version;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
@ -50,7 +51,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
CascadeMergeToProxyEntityCopyAllowedTest.Speaker.class CascadeMergeToProxyEntityCopyAllowedTest.Speaker.class
} }
) )
@SessionFactory @SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry( @ServiceRegistry(
settings = { settings = {
@ServiceRegistry.Setting( @ServiceRegistry.Setting(
@ -65,6 +66,8 @@ public class CascadeMergeToProxyEntityCopyAllowedTest {
public void test(SessionFactoryScope scope) { public void test(SessionFactoryScope scope) {
final Event root = (Event) persistEntity( scope, new Event( null, defaultProject ) ); final Event root = (Event) persistEntity( scope, new Event( null, defaultProject ) );
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
Event rootFromDB = scope.fromTransaction( Event rootFromDB = scope.fromTransaction(
session -> { session -> {
TypedQuery<Event> eventTypedQuery = session.createQuery( TypedQuery<Event> eventTypedQuery = session.createQuery(
@ -78,6 +81,8 @@ public class CascadeMergeToProxyEntityCopyAllowedTest {
} }
); );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 4 );
assertNotNull( rootFromDB ); assertNotNull( rootFromDB );
assertEquals( 0, rootFromDB.getChildren().size() ); assertEquals( 0, rootFromDB.getChildren().size() );
assertEquals( 0, rootFromDB.getSpeakers().size() ); assertEquals( 0, rootFromDB.getSpeakers().size() );
@ -113,7 +118,6 @@ public class CascadeMergeToProxyEntityCopyAllowedTest {
assertNotNull( rootFromDB ); assertNotNull( rootFromDB );
assertEquals( 1, rootFromDB.getChildren().size() ); assertEquals( 1, rootFromDB.getChildren().size() );
assertEquals( 0, rootFromDB.getSpeakers().size() ); assertEquals( 0, rootFromDB.getSpeakers().size() );
} }
private Object persistEntity(SessionFactoryScope scope, Object entity) { private Object persistEntity(SessionFactoryScope scope, Object entity) {

View File

@ -10,6 +10,8 @@ package org.hibernate.orm.test.cascade;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
public class H public class H
{ {

View File

@ -89,11 +89,11 @@ public class EagerManyToOneEmbeddedIdFKTest {
session -> { session -> {
System system = (System) session.createQuery( "from System e where e.id = :id" ) System system = (System) session.createQuery( "from System e where e.id = :id" )
.setParameter( "id", 1 ).uniqueResult(); .setParameter( "id", 1 ).uniqueResult();
statementInspector.assertExecutedCount( 2 );
assertThat( system, is( notNullValue() ) ); assertThat( system, is( notNullValue() ) );
SystemUser user = system.getUser(); SystemUser user = system.getUser();
assertThat( user, is( notNullValue() ) ); assertThat( user, is( notNullValue() ) );
statementInspector.assertExecutedCount( 2 );
} }
); );
} }

View File

@ -78,62 +78,6 @@ public class ManyToOneEmbeddedIdWithToOneFKTest {
public void testHql(SessionFactoryScope scope) { public void testHql(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear(); statementInspector.clear();
/*
select
s1_0.id,
s1_0.dataCenterUser_dataCenter_id,
s1_0.dataCenterUser_username,
s1_0.name
from
System s1_0
where
s1_0.id=?
select
d1_0.id,
d1_0.description
from
data_center as d1_0
where
d1_0.id = ?
select
d1_0.dataCenter_id,
d1_0.username,
d1_0.privilegeMask
from
data_center_user as d1_0
where
(
d1_0.dataCenter_id, d1_0.username
) in (
(
?, ?
)
)
NOTE: currently the 3rd query is:
select
d2_0.id,
d2_0.description,
d1_0.dataCenter_id,
d1_0.username,
d1_0.privilegeMask
from
data_center_user as d1_0
inner join
data_center as d2_0
on d1_0.dataCenter_id = d2_0.id
where
(
d1_0.dataCenter_id, d1_0.username
) in (
(
?, ?
)
)
*/
scope.inTransaction( scope.inTransaction(
session -> { session -> {
// this HQL should load the System with id = 1 // this HQL should load the System with id = 1
@ -228,22 +172,6 @@ public class ManyToOneEmbeddedIdWithToOneFKTest {
public void testHql2(SessionFactoryScope scope) { public void testHql2(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear(); statementInspector.clear();
/*
select
s1_0.subsystem_id,
s1_0.username,
s1_0.name
from
SystemUser as s1_0
select
s1_0.id,
s1_0.description
from
Subsystem s1_0
where
s1_0.id=?
*/
scope.inTransaction( scope.inTransaction(
session -> { session -> {
DataCenterUser system = (DataCenterUser) session.createQuery( "from DataCenterUser " ) DataCenterUser system = (DataCenterUser) session.createQuery( "from DataCenterUser " )
@ -260,7 +188,6 @@ public class ManyToOneEmbeddedIdWithToOneFKTest {
); );
} }
@BeforeEach @BeforeEach
public void setUp(SessionFactoryScope scope) { public void setUp(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(

View File

@ -42,7 +42,7 @@ import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetc
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
import org.hibernate.sql.results.graph.entity.EntityResult; import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchDelayedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchImpl;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -102,7 +102,7 @@ public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware
// Check the domain-result graph // Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, assertDomainResult( sqlAst, Cat.class, "owner", Person.class,
entityFetch -> assertThat( entityFetch, instanceOf( EntityFetchDelayedImpl.class ) ) entityFetch -> assertThat( entityFetch, instanceOf( EntityDelayedFetchImpl.class ) )
); );
} }
); );
@ -133,7 +133,7 @@ public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>(); final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class ); expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class ); expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class ); expectedFetchClassByAttributeName.put( "company", EntityDelayedFetchImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) ); assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
} }
} ); } );

View File

@ -0,0 +1,160 @@
/*
* 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.manytoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hibernate.orm.test.manytoone.ManyToOneBidirectionalCircularityTest.*;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityTest.class,
EntityTest2.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class ManyToOneBidirectionalCircularityTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 1, "e1" );
EntityTest2 entity2 = new EntityTest2( 2, "e2" );
entity.setEntity2( entity2 );
entity2.setEntity( entity );
session.save( entity2 );
session.save( entity );
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 1 );
EntityTest2 entity2 = entity.getEntity2();
assertThat( entity2.getName(), is( "e2" ) );
EntityTest entity3 = entity2.getEntity();
assertThat( entity3.getName(), is( "e1" ) );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery(
0,
"join",
1
);
}
);
}
@Entity(name = "EntityTest")
public static class EntityTest {
@Id
private Integer id;
private String name;
@ManyToOne
private EntityTest2 entity2;
public EntityTest() {
}
public EntityTest(int id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityTest2 getEntity2() {
return entity2;
}
public void setEntity2(EntityTest2 entity2) {
this.entity2 = entity2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "EntityTest2")
public static class EntityTest2 {
@Id
private Integer id;
private String name;
@OneToOne(mappedBy = "entity2")
private EntityTest entity;
public EntityTest2() {
}
public EntityTest2(int id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityTest getEntity() {
return entity;
}
public void setEntity(EntityTest entity) {
this.entity = entity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,157 @@
/*
* 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.manytoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hibernate.orm.test.manytoone.ManyToOneBidirectionalTest.*;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityTest.class,
EntityTest2.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class ManyToOneBidirectionalTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 1, "e1" );
EntityTest2 entity2 = new EntityTest2( 2, "e2" );
EntityTest entity3 = new EntityTest( 3, "e3" );
entity.setEntity2( entity2 );
entity2.setEntity( entity3 );
session.save( entity3 );
session.save( entity2 );
session.save( entity );
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
EntityTest entity = session.get( EntityTest.class, 1 );
EntityTest2 entity2 = entity.getEntity2();
assertThat( entity2.getName(), is( "e2" ) );
EntityTest entity3 = entity2.getEntity();
assertThat( entity3.getName(), is( "e3" ) );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
}
);
}
@Entity(name = "EntityTest")
public static class EntityTest {
@Id
private Integer id;
private String name;
@ManyToOne
private EntityTest2 entity2;
public EntityTest() {
}
public EntityTest(int id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityTest2 getEntity2() {
return entity2;
}
public void setEntity2(EntityTest2 entity2) {
this.entity2 = entity2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "EntityTest2")
public static class EntityTest2 {
@Id
private Integer id;
private String name;
@ManyToOne
private EntityTest entity;
public EntityTest2() {
}
public EntityTest2(int id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public EntityTest getEntity() {
return entity;
}
public void setEntity(EntityTest entity) {
this.entity = entity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -647,13 +647,11 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
"select o from Order o join fetch o.lineItems", "select o from Order o join fetch o.lineItems",
Order.class Order.class
).list(); ).list();
orders.forEach( order -> orders.forEach(
order.getLineItems().forEach( item -> order ->
assertThat( order.getLineItems().forEach(
item.getOrder(), item -> assertThat( item.getOrder(), sameInstance( order ) )
sameInstance( order ) )
)
)
); );
} ); } );
} }

View File

@ -0,0 +1,191 @@
/*
* 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.onetomany;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.orm.test.onetomany.OneToManyTest.Card;
import org.hibernate.orm.test.onetomany.OneToManyTest.CardField;
import org.hibernate.orm.test.onetomany.OneToManyTest.Key;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.fail;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
Card.class,
CardField.class,
Key.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class OneToManyTest {
public static final String CARD_ID = "cardId";
public static final String CARD_FIELD_ID = "cardFieldId";
public static final String KEY_ID = "keyId";
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Card card = new Card( CARD_ID );
Key key = new Key( KEY_ID );
card.addField( CARD_FIELD_ID, card, key );
session.persist( key );
session.persist( card );
}
);
}
@AfterEach
public void cleanUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Card card = session.get( Card.class, CARD_ID );
card.getFields().forEach(
cardField -> {
Key key = cardField.key;
session.delete( cardField );
session.delete( key );
}
);
session.delete( card );
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
try {
Card card = session.get( Card.class, CARD_ID );
assertEquals( 1, card.getFields().size() );
CardField cf = card.getFields().iterator().next();
assertSame( card, cf.getCard() );
}
catch (StackOverflowError soe) {
fail( "eager + key-many-to-one caused stack-overflow in annotations" );
}
}
);
}
@Entity(name = "Card")
public static class Card implements Serializable {
@Id
private String id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<CardField> fields;
Card() {
fields = new HashSet<>();
}
public Card(String id) {
this();
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void addField(String cardFieldId, Card card, Key key) {
fields.add( new CardField( cardFieldId, card, key ) );
}
public Set<CardField> getFields() {
return fields;
}
public void setFields(Set<CardField> fields) {
this.fields = fields;
}
}
@Entity(name = "CardField")
public static class CardField implements Serializable {
@Id
private String id;
@ManyToOne(optional = false)
private Card card;
@ManyToOne(optional = false)
private Key key;
CardField() {
}
public CardField(String id, Card card, Key key) {
this.id = id;
this.card = card;
this.key = key;
}
public Card getCard() {
return card;
}
}
@Entity(name = "Key")
@Table(name = "`key`")
public static class Key implements Serializable {
@Id
private String id;
public Key(String id) {
this.id = id;
}
Key() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
}

View File

@ -27,6 +27,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
/** /**
@ -34,12 +35,12 @@ import static org.hamcrest.MatcherAssert.assertThat;
*/ */
@DomainModel( @DomainModel(
annotatedClasses = { annotatedClasses = {
OneToOneLazy.Title.class, OneToOneLazyTest.Title.class,
OneToOneLazy.Book.class OneToOneLazyTest.Book.class
} }
) )
@SessionFactory @SessionFactory
public class OneToOneLazy { public class OneToOneLazyTest {
@BeforeEach @BeforeEach
public void setUp(SessionFactoryScope scope) { public void setUp(SessionFactoryScope scope) {
@ -59,15 +60,20 @@ public class OneToOneLazy {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
Book book = session.find( Book.class, 2L ); Book book = session.find( Book.class, 2L );
assertThat( Hibernate.isInitialized( book.getTitle() ), is( false ) ); Title title = book.getTitle();
assertThat( Hibernate.isInitialized( title ), is( false ) );
assertThat( title, notNullValue() );
assertThat( title.getId(), is( 1L ) );
} }
); );
scope.inTransaction( scope.inTransaction(
session -> { session -> {
Title title = session.find( Title.class, 1L ); Title title = session.find( Title.class, 1L );
assertThat( Hibernate.isInitialized( title.getBook() ), is( true ) ); Book book = title.getBook();
assertThat( Hibernate.isInitialized( book ), is( true ) );
assertThat( book, notNullValue() );
assertThat( book.getId(), is( 2L ) );
} }
); );
} }

View File

@ -23,9 +23,11 @@ import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.testing.jdbc.SQLStatementInspector; import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.junit5.EntityManagerFactoryBasedFunctionalTest; import org.hibernate.testing.junit5.EntityManagerFactoryBasedFunctionalTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.jupiter.api.Assertions.assertSame;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
@ -46,13 +48,9 @@ public class OneToOneMapsIdJoinColumnTest extends EntityManagerFactoryBasedFunct
}; };
} }
@Test @BeforeEach
public void testLifecycle() { public void setUp(){
EntityManagerFactory entityManagerFactory = entityManagerFactory(); doInJPA( this::entityManagerFactory, entityManager -> {
SessionFactory sessionFactory = entityManagerFactory.unwrap( SessionFactory.class );
SQLStatementInspector statementInspector = (SQLStatementInspector) sessionFactory.getSessionFactoryOptions().getStatementInspector();
Person _person = doInJPA( this::entityManagerFactory, entityManager -> {
Person person = new Person( "ABC-123" ); Person person = new Person( "ABC-123" );
@ -64,19 +62,34 @@ public class OneToOneMapsIdJoinColumnTest extends EntityManagerFactoryBasedFunct
return person; return person;
} ); } );
}
@Test
public void testLifecycle() {
SQLStatementInspector statementInspector = getSqlStatementInspector();
statementInspector.clear(); statementInspector.clear();
doInJPA( this::entityManagerFactory, entityManager -> { doInJPA( this::entityManagerFactory, entityManager -> {
Person person = entityManager.find( Person.class, _person.getId() ); Person person = entityManager.find( Person.class, "ABC-123" );
statementInspector.assertExecutedCount( 1 ); statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 ); statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
statementInspector.clear(); statementInspector.clear();
PersonDetails details = entityManager.find( PersonDetails.class, _person.getId() ); PersonDetails details = entityManager.find( PersonDetails.class, "ABC-123" );
statementInspector.assertExecutedCount( 0 );
assertSame(details.getPerson(), person);
statementInspector.assertExecutedCount( 0 ); statementInspector.assertExecutedCount( 0 );
} ); } );
} }
private SQLStatementInspector getSqlStatementInspector() {
EntityManagerFactory entityManagerFactory = entityManagerFactory();
SessionFactory sessionFactory = entityManagerFactory.unwrap( SessionFactory.class );
return (SQLStatementInspector) sessionFactory.getSessionFactoryOptions().getStatementInspector();
}
@Entity(name = "Person") @Entity(name = "Person")
public static class Person { public static class Person {

View File

@ -0,0 +1,116 @@
/*
* 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.onetoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.hibernate.testing.jdbc.SQLStatementInspector;
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.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hibernate.orm.test.onetoone.ToOneSelfReferenceTest.EntityTest;
/**
* @author Andrea Boriero
*/
@DomainModel(annotatedClasses = {
EntityTest.class
})
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class ToOneSelfReferenceTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityTest entity = new EntityTest( 1, "e1" );
EntityTest entity2 = new EntityTest( 2, "e2" );
EntityTest entity3 = new EntityTest( 3, "e3" );
entity2.setEntity( entity3 );
entity.setEntity( entity2 );
session.save( entity3 );
session.save( entity2 );
session.save( entity );
}
);
}
@Test
public void testGet(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction(
session -> {
final EntityTest entity = session.get( EntityTest.class, 1 );
assertThat( entity.getName(), is( "e1" ) );
final EntityTest entity2 = entity.getEntity();
assertThat( entity2, notNullValue() );
assertThat( entity2.getName(), is( "e2" ) );
final EntityTest entity3 = entity2.getEntity();
assertThat( entity3, notNullValue() );
assertThat( entity3.getName(), is( "e3" ) );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
}
);
}
@Entity(name = "EntityTest")
public static class EntityTest {
@Id
private Integer id;
private String name;
@ManyToOne
private EntityTest entity;
public EntityTest() {
}
public EntityTest(int id, String name) {
this.id = id;
this.name = name;
}
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 EntityTest getEntity() {
return entity;
}
public void setEntity(EntityTest entity) {
this.entity = entity;
}
}
}

View File

@ -48,7 +48,7 @@ import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetc
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
import org.hibernate.sql.results.graph.entity.EntityResult; import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchDelayedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchImpl;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -106,7 +106,7 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
// Check the domain-result graph // Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, assertDomainResult( sqlAst, Cat.class, "owner", Person.class,
entityFetch -> assertThat( entityFetch, instanceOf( EntityFetchDelayedImpl.class ) ) entityFetch -> assertThat( entityFetch, instanceOf( EntityDelayedFetchImpl.class ) )
); );
} }
); );
@ -137,7 +137,7 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>(); final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class ); expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class ); expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class ); expectedFetchClassByAttributeName.put( "company", EntityDelayedFetchImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) ); assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
} }
} ); } );

View File

@ -46,7 +46,7 @@ import org.hibernate.sql.results.graph.collection.internal.DelayedCollectionFetc
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
import org.hibernate.sql.results.graph.entity.EntityResult; import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchDelayedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchImpl;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -104,7 +104,7 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
// Check the domain-result graph // Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, assertDomainResult( sqlAst, Cat.class, "owner", Person.class,
entityFetch -> assertThat( entityFetch, instanceOf( EntityFetchDelayedImpl.class ) ) entityFetch -> assertThat( entityFetch, instanceOf( EntityDelayedFetchImpl.class ) )
); );
} }
); );
@ -135,7 +135,7 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>(); final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class ); expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class ); expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class ); expectedFetchClassByAttributeName.put( "company", EntityDelayedFetchImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) ); assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
} }
} ); } );

View File

@ -11,6 +11,7 @@ import java.util.List;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.domain.gambit.EntityWithManyToOneSelfReference; import org.hibernate.testing.orm.domain.gambit.EntityWithManyToOneSelfReference;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected; import org.hibernate.testing.orm.junit.FailureExpected;
@ -37,7 +38,7 @@ import static org.junit.Assert.assertTrue;
} }
) )
@ServiceRegistry @ServiceRegistry
@SessionFactory(generateStatistics = true) @SessionFactory(generateStatistics = true, statementInspectorClass = SQLStatementInspector.class)
public class EntityWithManyToOneSelfReferenceTest { public class EntityWithManyToOneSelfReferenceTest {
@BeforeEach @BeforeEach
@ -95,8 +96,8 @@ public class EntityWithManyToOneSelfReferenceTest {
@Test @Test
public void testGetEntity(SessionFactoryScope scope) { public void testGetEntity(SessionFactoryScope scope) {
StatisticsImplementor statistics = scope.getSessionFactory().getStatistics(); SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statistics.clear(); statementInspector.clear();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final EntityWithManyToOneSelfReference loaded = session.get( final EntityWithManyToOneSelfReference loaded = session.get(
@ -104,7 +105,8 @@ public class EntityWithManyToOneSelfReferenceTest {
2 2
); );
assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
assertThat( loaded, notNullValue() ); assertThat( loaded, notNullValue() );
assertThat( loaded.getName(), is( "second" ) ); assertThat( loaded.getName(), is( "second" ) );
@ -113,18 +115,20 @@ public class EntityWithManyToOneSelfReferenceTest {
assertTrue( Hibernate.isInitialized( other ) ); assertTrue( Hibernate.isInitialized( other ) );
assertThat( other.getName(), is( "first" ) ); assertThat( other.getName(), is( "first" ) );
assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); statementInspector.assertExecutedCount( 1 );
} }
); );
statistics.clear(); statementInspector.clear();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final EntityWithManyToOneSelfReference loaded = session.get( final EntityWithManyToOneSelfReference loaded = session.get(
EntityWithManyToOneSelfReference.class, EntityWithManyToOneSelfReference.class,
1 1
); );
assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
assertThat( loaded, notNullValue() ); assertThat( loaded, notNullValue() );
assertThat( loaded.getName(), is( "first" ) ); assertThat( loaded.getName(), is( "first" ) );

View File

@ -42,7 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
) )
@ServiceRegistry @ServiceRegistry
@SessionFactory(generateStatistics = true) @SessionFactory(generateStatistics = true)
public class EntityWithLazyOneToOneTest { public class EntityWithLazyBidirectionalOneToOneTest {
@BeforeEach @BeforeEach
public void setUp(SessionFactoryScope scope) { public void setUp(SessionFactoryScope scope) {

View File

@ -15,6 +15,7 @@ import javax.persistence.Table;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
@ -27,6 +28,10 @@ import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Female;
import static org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Male;
import static org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Parent;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
@ -34,13 +39,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/ */
@DomainModel( @DomainModel(
annotatedClasses = { annotatedClasses = {
EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Parent.class, Parent.class,
EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Child.class, Male.class,
EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Child2.class, Female.class,
} }
) )
@ServiceRegistry @ServiceRegistry
@SessionFactory(generateStatistics = true) @SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest { public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
@BeforeEach @BeforeEach
@ -48,13 +53,16 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
Parent parent = new Parent( 1, "Hibernate" ); Parent parent = new Parent( 1, "Hibernate" );
Child child = new Child( 2, parent );
child.setName( "Acme" ); Male son = new Male( 2, parent );
Child2 child2 = new Child2( 3, parent ); son.setName( "Luigi" );
child2.setName( "Fab" );
Female daughter = new Female( 3, parent );
daughter.setName( "Fab" );
session.save( parent ); session.save( parent );
session.save( child ); session.save( son );
session.save( child2 ); session.save( daughter );
} ); } );
} }
@ -63,43 +71,50 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
session.createQuery( "delete from Parent" ).executeUpdate(); session.createQuery( "delete from Parent" ).executeUpdate();
session.createQuery( "delete from Child" ).executeUpdate(); session.createQuery( "delete from Male" ).executeUpdate();
session.createQuery( "delete from Child2" ).executeUpdate(); session.createQuery( "delete from Female" ).executeUpdate();
} ); } );
} }
@Test @Test
public void testGetParent(SessionFactoryScope scope) { public void testGetParent(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final Parent parent = session.get( Parent.class, 1 ); final Parent parent = session.get( Parent.class, 1 );
Child child = parent.getChild(); statementInspector.assertExecutedCount( 1 );
assertThat( child, CoreMatchers.notNullValue() ); statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 6 );
Male son = parent.getSon();
assertThat( son, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child ), Hibernate.isInitialized( son ),
"The child eager OneToOne association is not initialized" "The son eager OneToOne association is not initialized"
); );
assertThat( child.getName(), equalTo( "Acme" ) ); assertThat( son.getName(), equalTo( "Luigi" ) );
assertThat( child.getParent(), CoreMatchers.notNullValue() ); assertSame( son.getParent(), parent );
Female daughter = parent.getDaughter();
Child2 child2 = parent.getChild2(); assertThat( daughter, CoreMatchers.notNullValue() );
assertThat( child2, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child2 ), Hibernate.isInitialized( daughter ),
"The child2 eager OneToOne association is not initialized" "The daughter eager OneToOne association is not initialized"
); );
assertThat( child2.getName(), equalTo( "Fab" ) ); assertThat( daughter.getName(), equalTo( "Fab" ) );
assertThat( child2.getParent(), CoreMatchers.notNullValue() ); assertSame( daughter.getParent(), parent );
statementInspector.assertExecutedCount( 1 );
} ); } );
} }
@Test @Test
public void testGetChild(SessionFactoryScope scope) { public void testGetChild(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> { scope.inTransaction( session -> {
final Child child = session.get( Child.class, 2 ); final Male son = session.get( Male.class, 2 );
Parent parent = child.getParent(); statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 6 );
Parent parent = son.getParent();
assertThat( parent, CoreMatchers.notNullValue() ); assertThat( parent, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( parent ), Hibernate.isInitialized( parent ),
@ -107,36 +122,41 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
); );
assertThat( parent.getDescription(), CoreMatchers.notNullValue() ); assertThat( parent.getDescription(), CoreMatchers.notNullValue() );
Child child1 = parent.getChild();
assertThat( child1, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child1 ), Hibernate.isInitialized( parent.getSon() ),
"The child eager OneToOne association is not initialized" "The son eager OneToOne association is not initialized"
); );
assertSame( parent.getSon(), son );
Child2 child2 = parent.getChild2(); Female daughter = parent.getDaughter();
assertThat( child2, CoreMatchers.notNullValue() ); assertThat( daughter, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child2 ), Hibernate.isInitialized( daughter ),
"The child2 eager OneToOne association is not initialized" "The child2 eager OneToOne association is not initialized"
); );
assertThat( child2.getParent(), CoreMatchers.notNullValue() ); assertThat( daughter.getParent(), CoreMatchers.notNullValue() );
statementInspector.assertExecutedCount( 1 );
} ); } );
} }
@Test @Test
public void testHqlSelectChild(SessionFactoryScope scope) { public void testHqlSelectSon(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final String queryString = "SELECT c FROM Child c JOIN c.parent d WHERE d.id = :id"; final String queryString = "SELECT m FROM Male m JOIN m.parent d WHERE d.id = :id";
final Child child = session.createQuery( queryString, Child.class ) final Male son = session.createQuery( queryString, Male.class )
.setParameter( "id", 1 ) .setParameter( "id", 1 )
.getSingleResult(); .getSingleResult();
assertThat( child.getParent(), CoreMatchers.notNullValue() ); statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 6 );
assertThat( son.getParent(), CoreMatchers.notNullValue() );
String description = child.getParent().getDescription(); String description = son.getParent().getDescription();
assertThat( description, CoreMatchers.notNullValue() ); assertThat( description, CoreMatchers.notNullValue() );
} }
); );
@ -146,20 +166,24 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
public void testHqlSelectParent(SessionFactoryScope scope) { public void testHqlSelectParent(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
final Parent parent = session.createQuery( final Parent parent = session.createQuery(
"SELECT p FROM Parent p JOIN p.child WHERE p.id = :id", "SELECT p FROM Parent p JOIN p.son WHERE p.id = :id",
Parent.class Parent.class
) )
.setParameter( "id", 1 ) .setParameter( "id", 1 )
.getSingleResult(); .getSingleResult();
statementInspector.assertExecutedCount( 2 );
Child child = parent.getChild(); statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
assertThat( child, CoreMatchers.notNullValue() ); statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 6 );
Male son = parent.getSon();
assertThat( son, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child ), Hibernate.isInitialized( son ),
"the child have to be initialized" "the son have to be initialized"
); );
String name = child.getName(); String name = son.getName();
assertThat( name, CoreMatchers.notNullValue() ); assertThat( name, CoreMatchers.notNullValue() );
} }
@ -168,19 +192,19 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final Parent parent = session.createQuery( final Parent parent = session.createQuery(
"SELECT p FROM Parent p JOIN p.child WHERE p.id = :id", "SELECT p FROM Parent p JOIN p.son WHERE p.id = :id",
Parent.class Parent.class
) )
.setParameter( "id", 1 ) .setParameter( "id", 1 )
.getSingleResult(); .getSingleResult();
Child child = parent.getChild(); Male son = parent.getSon();
assertThat( child, CoreMatchers.notNullValue() ); assertThat( son, CoreMatchers.notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child ), Hibernate.isInitialized( son ),
"The child have to be initialized" "The son have to be initialized"
); );
String name = child.getName(); String name = son.getName();
assertThat( name, CoreMatchers.notNullValue() ); assertThat( name, CoreMatchers.notNullValue() );
} }
@ -193,8 +217,8 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
private Integer id; private Integer id;
private String description; private String description;
private Child child; private Male son;
private Child2 child2; private Female daughter;
Parent() { Parent() {
} }
@ -222,40 +246,40 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
} }
@OneToOne @OneToOne
@JoinTable(name = "PARENT_CHILD", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id")) @JoinTable(name = "PARENT_SON", inverseJoinColumns = @JoinColumn(name = "son_id"), joinColumns = @JoinColumn(name = "parent_id"))
public Child getChild() { public Male getSon() {
return child; return son;
} }
public void setChild(Child other) { public void setSon(Male son) {
this.child = other; this.son = son;
} }
@OneToOne @OneToOne
public Child2 getChild2() { public Female getDaughter() {
return child2; return daughter;
} }
public void setChild2(Child2 child2) { public void setDaughter(Female daughter) {
this.child2 = child2; this.daughter = daughter;
} }
} }
@Entity(name = "Child") @Entity(name = "Male")
@Table(name = "CHILD") @Table(name = "MALE")
public static class Child { public static class Male {
private Integer id; private Integer id;
private String name; private String name;
private Parent parent; private Parent parent;
Child() { Male() {
} }
Child(Integer id, Parent parent) { Male(Integer id, Parent parent) {
this.id = id; this.id = id;
this.parent = parent; this.parent = parent;
this.parent.setChild( this ); this.parent.setSon( this );
} }
@Id @Id
@ -275,7 +299,7 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
this.name = name; this.name = name;
} }
@OneToOne(mappedBy = "child") @OneToOne(mappedBy = "son")
public Parent getParent() { public Parent getParent() {
return parent; return parent;
} }
@ -285,21 +309,21 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
} }
} }
@Entity(name = "Child2") @Entity(name = "Female")
@Table(name = "CHILD2") @Table(name = "FEMALE")
public static class Child2 { public static class Female {
private Integer id; private Integer id;
private String name; private String name;
private Parent parent; private Parent parent;
Child2() { Female() {
} }
Child2(Integer id, Parent child) { Female(Integer id, Parent child) {
this.id = id; this.id = id;
this.parent = child; this.parent = child;
this.parent.setChild2( this ); this.parent.setDaughter( this );
} }
@Id @Id
@ -319,7 +343,7 @@ public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
this.name = name; this.name = name;
} }
@OneToOne(mappedBy = "child2") @OneToOne(mappedBy = "daughter")
public Parent getParent() { public Parent getParent() {
return parent; return parent;
} }

View File

@ -12,20 +12,27 @@ import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.validator.internal.util.Contracts;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel; 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.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalOneToOneTest.AdoptedChild;
import static org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalOneToOneTest.Child;
import static org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalOneToOneTest.Mother;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
@ -33,248 +40,438 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/ */
@DomainModel( @DomainModel(
annotatedClasses = { annotatedClasses = {
EntityWithBidirectionalOneToOneTest.Parent.class, Mother.class,
EntityWithBidirectionalOneToOneTest.Child.class, Child.class,
EntityWithBidirectionalOneToOneTest.Child2.class AdoptedChild.class
} }
) )
@ServiceRegistry @ServiceRegistry
@SessionFactory(generateStatistics = true) @SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class EntityWithBidirectionalOneToOneTest { public class EntityWithBidirectionalOneToOneTest {
@BeforeEach @BeforeEach
public void setUp(SessionFactoryScope scope) { public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> { scope.inTransaction( session -> {
Parent parent = new Parent( 1, "Hibernate ORM" ); Mother mother = new Mother( 1, "Giulia" );
Child child = new Child( 2, parent );
child.setName( "Acme" ); Child child = new Child( 2, "Luis", mother );
Child2 child2 = new Child2( 3, parent );
child2.setName( "Fab" ); AdoptedChild adoptedChild = new AdoptedChild( 3, "Fab", mother );
session.save( parent );
session.save( mother );
session.save( child ); session.save( child );
session.save( child2 ); session.save( adoptedChild );
} ); } );
} }
@AfterEach @AfterEach
public void tearDown(SessionFactoryScope scope) { public void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> { scope.inTransaction( session -> {
session.createQuery( "delete from Child2" ).executeUpdate(); session.createQuery( "delete from AdoptedChild" ).executeUpdate();
session.createQuery( "delete from Parent" ).executeUpdate(); session.createQuery( "delete from Mother" ).executeUpdate();
session.createQuery( "delete from Child" ).executeUpdate(); session.createQuery( "delete from Child" ).executeUpdate();
} ); } );
} }
@Test @Test
public void testGetParent(SessionFactoryScope scope) { public void testGetMother(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> { scope.inTransaction( session -> {
final Parent parent = session.get( Parent.class, 1 ); final Mother mother = session.get( Mother.class, 1 );
Child child = parent.getOwnedBidirectionalChild();
Child child = mother.getBiologicalChild();
assertThat( child, notNullValue() ); assertThat( child, notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child ), Hibernate.isInitialized( child ),
"The child eager OneToOne association is not initialized" "The child eager OneToOne association is not initialized"
); );
assertThat( child.getName(), notNullValue() ); assertThat( child.getName(), is( "Luis" ) );
assertThat( child.getParentMappedByChild(), notNullValue() ); assertSame( child.getMother(), mother );
assertThat( child.getParentMappedByChild(), notNullValue() );
Child2 child2 = parent.getChildMappedByParent1(); AdoptedChild adoptedChild = mother.getAdopted();
assertThat( child2, notNullValue() ); assertThat( adoptedChild.getName(), is( "Fab" ) );
assertTrue( assertTrue(
Hibernate.isInitialized( child2 ), Hibernate.isInitialized( adoptedChild ),
"The child2 eager OneToOne association is not initialized" "The adoptedChild eager OneToOne association is not initialized"
); );
assertThat( child2.getName(), equalTo( "Fab" ) ); assertThat( adoptedChild.getName(), equalTo( "Fab" ) );
assertThat( child2.getOwnedBidirectionalParent(), notNullValue() );
assertSame( adoptedChild.getStepMother(), mother );
assertThat( adoptedChild.getBiologicalMother(), is( nullValue() ) );
/*
fetchablePath: Mother.biologicalChild --- NO circular --- first join created
fetchablePath: Mother.biologicalChild.mother --- Circular ---
fetchablePath: Mother.adopted --- NO circular --- second join created
fetchablePath: Mother.adopted.biologicalMother --- NO circular --- third join created
fetchablePath: Mother.adopted.biologicalMother.biologicalChild --- NO circular --- fourth join created
fetchablePath: Mother.adopted.biologicalMother.biologicalChild.mother --- Circular ---
fetchablePath: Mother.adopted.biologicalMother.adopted --- NO circular --- fifth join created
fetchablePath: Mother.adopted.biologicalMother.adopted.biologicalMother --- NO circular --- sixth join created
fetchablePath: Mother.adopted.biologicalMother.adopted.biologicalMother.biologicalChild --- NO circular --- seventh join created
fetchablePath: Mother.adopted.biologicalMother.adopted.biologicalMother.biologicalChild.mother --- Circular ---
fetchablePath: Mother.adopted.biologicalMother.adopted.biologicalMother.adopted --- NO circular --- eighth join created
fetchablePath: Mother.adopted.biologicalMother.adopted.biologicalMother.adopted.biologicalMother --- NO circular --- max fetch depth reached no join created
fetchablePath: Mother.adopted.biologicalMother.adopted.biologicalMother.adopted.stepMother --- Circular ---
fetchablePath: Mother.adopted.biologicalMother.adopted.stepMother --- Circular ---
fetchablePath org.hibernate.orm.test.sql.exec.onetoone.bidirectional.EntityWithBidirectionalOneToOneTest$Mother.adopted.stepMother --- Circular ---
*/
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 4 );
} ); } );
} }
@Test @Test
public void testGetParent2(SessionFactoryScope scope) { public void testUnrealCaseWhenMotherIsAlsoStepMother(SessionFactoryScope scope) {
scope.inTransaction( session -> { scope.inTransaction( session -> {
Parent parent = new Parent( 4, "Hibernate OGM" ); Mother mother = new Mother( 4, "Jiny" );
Child child = new Child( 5, parent );
child.setName( "Acme2" );
Child2 child2 = new Child2( 6, parent ); Child child = new Child( 5, "Carlo", mother );
child2.setName( "Fab2" );
child2.setUnidirectionalParent( parent ); AdoptedChild adoptedChild = new AdoptedChild( 6, "Andrea", mother );
session.save( parent ); adoptedChild.setBiologicalMother( mother );
session.save( mother );
session.save( child ); session.save( child );
session.save( child2 ); session.save( adoptedChild );
} ); } );
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> { scope.inTransaction( session -> {
final Parent parent = session.get( Parent.class, 4 ); final Mother mother = session.get( Mother.class, 4 );
Child child = parent.getOwnedBidirectionalChild();
Child child = mother.getBiologicalChild();
assertThat( child, notNullValue() ); assertThat( child, notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child ), Hibernate.isInitialized( child ),
"The child eager OneToOne association is not initialized" "The child eager OneToOne association is not initialized"
); );
assertThat( child.getName(), notNullValue() ); assertThat( child.getName(), is( "Carlo" ) );
assertThat( child.getParentMappedByChild(), notNullValue() ); assertSame( child.getMother(), mother );
Child2 child2 = parent.getChildMappedByParent1(); AdoptedChild adoptedChild = mother.getAdopted();
assertThat( child2, notNullValue() ); assertThat( adoptedChild, notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child2 ), Hibernate.isInitialized( adoptedChild ),
"The child2 eager OneToOne association is not initialized" "The adoptedChild eager OneToOne association is not initialized"
); );
assertThat( child2.getName(), equalTo( "Fab2" ) ); assertThat( adoptedChild.getName(), equalTo( "Andrea" ) );
assertThat( child2.getOwnedBidirectionalParent(), notNullValue() );
assertThat( child2.getOwnedBidirectionalParent().getDescription(), equalTo( "Hibernate OGM" ) );
Parent parent2 = child2.getUnidirectionalParent(); assertSame( adoptedChild.getStepMother(), mother );
assertThat( parent2, notNullValue() ); assertSame( adoptedChild.getBiologicalMother(), mother );
assertThat( parent2.getDescription(), equalTo( "Hibernate OGM" ) );
assertThat( parent2.getOwnedBidirectionalChild(), notNullValue() );
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 4 );
} ); } );
} }
@Test @Test
public void testGetParent3(SessionFactoryScope scope) { public void testGetMother3(SessionFactoryScope scope) {
scope.inTransaction( session -> { scope.inTransaction( session -> {
Parent parent = new Parent( 4, "Hibernate Search" ); Mother mother = new Mother( 4, "Catia" );
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" ); Child child = new Child( 5, "Stefano", mother );
child2.setUnidirectionalParent( parent2 );
Child child1 = new Child( 8, parent2 ); AdoptedChild adoptedChild = new AdoptedChild( 7, "Luisa", mother );
session.save( parent ); Mother biologicalMother = new Mother( 6, "Rebecca" );
session.save( parent2 ); adoptedChild.setBiologicalMother( biologicalMother );
Child anotherChild = new Child( 8, "Igor", biologicalMother );
session.save( mother );
session.save( biologicalMother );
session.save( child ); session.save( child );
session.save( child1 ); session.save( adoptedChild );
session.save( child2 ); session.save( anotherChild );
} ); } );
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> { scope.inTransaction( session -> {
final Parent parent = session.get( Parent.class, 4 ); final Mother mother = session.get( Mother.class, 4 );
assertThat( parent.getDescription(), equalTo( "Hibernate Search" ) );
Child child = parent.getOwnedBidirectionalChild(); assertThat( mother.getName(), equalTo( "Catia" ) );
assertThat( child, notNullValue() );
Child procreatedChild = mother.getBiologicalChild();
assertThat( procreatedChild, notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child ), Hibernate.isInitialized( procreatedChild ),
"The child eager OneToOne association is not initialized" "The procreatedChild eager OneToOne association is not initialized"
); );
assertThat( child.getName(), notNullValue() ); assertThat( procreatedChild.getName(), equalTo( "Stefano" ) );
assertThat( child.getParentMappedByChild(), notNullValue() ); assertSame( procreatedChild.getMother(), mother );
Child2 child2 = parent.getChildMappedByParent1(); AdoptedChild adoptedChild = mother.getAdopted();
assertThat( child2, notNullValue() ); assertThat( adoptedChild, notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child2 ), Hibernate.isInitialized( adoptedChild ),
"The child2 eager OneToOne association is not initialized" "The adoptedChild eager OneToOne association is not initialized"
); );
assertThat( child2.getName(), equalTo( "Fab2" ) ); assertThat( adoptedChild.getName(), equalTo( "Luisa" ) );
assertThat( child2.getOwnedBidirectionalParent(), notNullValue() ); assertSame( adoptedChild.getStepMother(), mother );
assertThat( child2.getOwnedBidirectionalParent().getDescription(), equalTo( "Hibernate Search" ) );
Parent parent2 = child2.getUnidirectionalParent(); Mother biologicalMother = adoptedChild.getBiologicalMother();
assertThat( parent2, notNullValue() ); assertThat( biologicalMother.getId(), equalTo( 6 ) );
assertThat( parent2.getDescription(), equalTo( "Hibernate OGM" ) ); assertThat( biologicalMother.getAdopted(), nullValue() );
assertThat( parent2.getOwnedBidirectionalChild(), notNullValue() );
Child anotherChild = biologicalMother.getBiologicalChild();
assertThat( anotherChild.getId(), equalTo( 8 ) );
assertThat( anotherChild.getName(), equalTo( "Igor" ) );
assertSame( biologicalMother, anotherChild.getMother() );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 4);
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 4);
} ); } );
} }
@Test @Test
public void testGetChild(SessionFactoryScope scope) { public void testGetChild(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> { scope.inTransaction( session -> {
final Child child = session.get( Child.class, 2 ); final Child child = session.get( Child.class, 2 );
Parent parent = child.getParentMappedByChild();
Mother mother = child.getMother();
assertTrue( assertTrue(
Hibernate.isInitialized( parent ), Hibernate.isInitialized( mother ),
"The parent eager OneToOne association is not initialized" "The mother eager OneToOne association is not initialized"
); );
assertThat( parent, notNullValue() ); assertThat( mother, notNullValue() );
assertThat( parent.getDescription(), notNullValue() ); assertThat( mother.getName(), is( "Giulia" ) );
Child child1 = parent.getOwnedBidirectionalChild();
assertThat( child1, notNullValue() ); Child biologicalChild = mother.getBiologicalChild();
assertSame( biologicalChild, child );
assertTrue( assertTrue(
Hibernate.isInitialized( child1 ), Hibernate.isInitialized( biologicalChild ),
"The child eager OneToOne association is not initialized" "The child eager OneToOne association is not initialized"
); );
Child2 child2 = parent.getChildMappedByParent1();
assertThat( child2, notNullValue() ); AdoptedChild adoptedChild = mother.getAdopted();
assertThat( adoptedChild, notNullValue() );
assertTrue( assertTrue(
Hibernate.isInitialized( child2 ), Hibernate.isInitialized( adoptedChild ),
"The child2 eager OneToOne association is not initialized" "The adoptedChild eager OneToOne association is not initialized"
); );
assertThat( child2.getOwnedBidirectionalParent(), notNullValue() ); assertSame( adoptedChild.getStepMother(), mother );
assertThat( child2.getUnidirectionalParent(), nullValue() ); assertThat( adoptedChild.getBiologicalMother(), nullValue() );
statementInspector.assertExecutedCount( 1 );
/*
fetchablePath: Child.mother --- NO circular --- first join created
fetchablePath: Child.mother.biologicalChild --- Circular ---
fetchablePath: Child.mother.adopted --- NO circular --- second join created
fetchablePath: Child.mother.adopted.biologicalMother --- NO circular --- third join created
fetchablePath: Child.mother.adopted.biologicalMother.biologicalChild --- NO circular --- fourth join created
fetchablePath: Child.mother.adopted.biologicalMother.biologicalChild.mother --- Circular ---
fetchablePath: Child.mother.adopted.biologicalMother.adopted --- NO circular --- fifth join created
fetchablePath: Child.mother.adopted.biologicalMother.adopted.biologicalMother --- NO circular --- sixth join created
fetchablePath: Child.mother.adopted.biologicalMother.adopted.biologicalMother.biologicalChild --- NO circular --- max fetch depth reached no join created
fetchablePath Child.mother.adopted.biologicalMother.adopted.biologicalMother.adopted --- NO circular --- max fetch depth reached no join created
fetchablePath Child.mother.adopted.biologicalMother.adopted.stepMother --- Circular ---
fetchablePath Child.mother.adopted.stepMother --- Circular --
*/
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 4 );
} ); } );
} }
@Test @Test
public void testHqlSelectParent(SessionFactoryScope scope) { public void testGetAdoptedChild(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> {
final AdoptedChild adoptedChild = session.get( AdoptedChild.class, 3 );
Mother stepMother = adoptedChild.getStepMother();
assertTrue(
Hibernate.isInitialized( stepMother ),
"The stepMother eager OneToOne association is not initialized"
);
assertThat( stepMother, notNullValue() );
assertThat( stepMother.getName(), is( "Giulia" ) );
Child biologicalChild = stepMother.getBiologicalChild();
assertThat( biologicalChild, notNullValue() );
assertThat( biologicalChild.getId(), is(2) );
assertTrue(
Hibernate.isInitialized( biologicalChild ),
"The biological eager OneToOne association is not initialized"
);
assertSame( adoptedChild, stepMother.getAdopted() );
assertTrue(
Hibernate.isInitialized( adoptedChild ),
"The adoptedChild eager OneToOne association is not initialized"
);
assertThat( adoptedChild.getBiologicalMother(), nullValue() );
statementInspector.assertExecutedCount( 2 );
/*
fetchablePath: AdoptedChild.biologicalMother --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.biologicalChild --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.biologicalChild.mother --- Circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother.biologicalChild --- NO circular --- [N.b is is not circular because adoped is an instance of AdoptedChild while biologicalChild is an instance of Child]
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother.adopted --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother.adopted.biologicalMother --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother.adopted.biologicalMother.biologicalChild --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother.adopted.biologicalMother.adopted --- NO circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.biologicalMother.adopted.stepMother --- Circular ---
fetchablePath: AdoptedChild.biologicalMother.adopted.stepMother --- Circular ---
fetchablePath: AdoptedChild.stepMother --- NO circular ---
fetchablePath: AdoptedChild.stepMother.biologicalChild --- NO circular ---
fetchablePath: AdoptedChild.stepMother.biologicalChild.mother --- Circular ---
fetchablePath: AdoptedChild.stepMother.adopted --- Circular ---
*/
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 3 );
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 4 );
} );
}
@Test
public void testGetChild2(SessionFactoryScope scope) {
scope.inTransaction( session -> {
Mother mother = new Mother( 4, "Giulia" );
Child child = new Child( 5, "Stefano", mother );
AdoptedChild child2 = new AdoptedChild( 7, "Fab2", mother );
Mother biologicalMother = new Mother( 6, "Hibernate OGM" );
child2.setBiologicalMother( biologicalMother );
Child child3 = new Child( 8, "Carla", biologicalMother );
session.save( mother );
session.save( biologicalMother );
session.save( child );
session.save( child2 );
session.save( child3 );
} );
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( session -> {
final Child child = session.get( Child.class, 5 );
Mother mother = child.getMother();
Contracts.assertTrue(
Hibernate.isInitialized( mother ),
"The mother eager OneToOne association is not initialized"
);
assertThat( mother, notNullValue() );
assertThat( mother.getName(), is( "Giulia" ) );
Child child1 = mother.getBiologicalChild();
assertSame( child1, child );
Contracts.assertTrue(
Hibernate.isInitialized( child1 ),
"The child eager OneToOne association is not initialized"
);
AdoptedChild adoptedChild = mother.getAdopted();
assertThat( adoptedChild, notNullValue() );
Contracts.assertTrue(
Hibernate.isInitialized( adoptedChild ),
"The adoptedChild eager OneToOne association is not initialized"
);
Assert.assertSame( adoptedChild.getStepMother(), mother );
Mother biologicalMother = adoptedChild.getBiologicalMother();
assertThat( biologicalMother, notNullValue() );
assertThat( biologicalMother.getId(), equalTo( 6 ) );
Child anotherChild = biologicalMother.getBiologicalChild();
assertThat( anotherChild, notNullValue() );
assertThat( anotherChild.getId(), equalTo( 8 ) );
Assert.assertSame( anotherChild.getMother(), biologicalMother );
assertThat( biologicalMother.getAdopted(), nullValue() );
statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 4 );
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 4 );
} );
}
@Test
public void testHqlSelectMother(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final Parent parent = session.createQuery( final Mother mother = session.createQuery(
"SELECT p FROM Parent p JOIN p.ownedBidirectionalChild WHERE p.id = :id", "SELECT m FROM Mother m JOIN m.biologicalChild WHERE m.id = :id",
Parent.class Mother.class
) )
.setParameter( "id", 1 ) .setParameter( "id", 1 )
.getSingleResult(); .getSingleResult();
assertThat( parent.getOwnedBidirectionalChild(), notNullValue() ); Child child = mother.getBiologicalChild();
String name = parent.getOwnedBidirectionalChild().getName(); assertThat( child, notNullValue() );
assertThat( name, notNullValue() ); assertThat( child.getName(), is( "Luis" ) );
statementInspector.assertExecutedCount( 3 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
// Mother.biologicalChild
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 4 );
// Mother.adopted
statementInspector.assertNumberOfOccurrenceInQuery( 2, "join", 3 );
} }
); );
} }
@Test @Test
@FailureExpected
public void testHqlSelectChild(SessionFactoryScope scope) { public void testHqlSelectChild(SessionFactoryScope scope) {
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
statementInspector.clear();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final String queryString = "SELECT c FROM Child c JOIN c.parentMappedByChild d WHERE d.id = :id"; final String queryString = "SELECT c FROM Child c JOIN c.mother d WHERE d.id = :id";
final Child child = session.createQuery( queryString, Child.class ) final Child child = session.createQuery( queryString, Child.class )
.setParameter( "id", 1 ) .setParameter( "id", 1 )
.getSingleResult(); .getSingleResult();
assertThat( child.getParentMappedByChild(), notNullValue() ); Mother mother = child.getMother();
assertThat( mother, notNullValue() );
String description = child.getParentMappedByChild().getDescription(); assertThat( mother.getName(), is( "Giulia" ) );
assertThat( description, notNullValue() ); statementInspector.assertExecutedCount( 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 4 );
} }
); );
} }
@Entity(name = "Parent") @Entity(name = "Mother")
public static class Parent { public static class Mother {
@Id @Id
private Integer id; private Integer id;
private String description; private String name;
@OneToOne @OneToOne
private Child ownedBidirectionalChild; private Child biologicalChild;
@OneToOne(mappedBy = "ownedBidirectionalParent") @OneToOne(mappedBy = "stepMother")
private Child2 childMappedByParent1; private AdoptedChild adopted;
Parent() { Mother() {
} }
public Parent(Integer id, String description) { public Mother(Integer id, String name) {
this.id = id; this.id = id;
this.description = description; this.name = name;
} }
Parent(Integer id) { Mother(Integer id) {
this.id = id; this.id = id;
} }
@ -286,30 +483,29 @@ public class EntityWithBidirectionalOneToOneTest {
this.id = id; this.id = id;
} }
public String getDescription() { public String getName() {
return description; return name;
} }
public void setDescription(String description) { public void setName(String name) {
this.description = description; this.name = name;
} }
public Child getOwnedBidirectionalChild() { public Child getBiologicalChild() {
return ownedBidirectionalChild; return biologicalChild;
} }
public void setOwnedBidirectionalChild(Child ownedBidirectionalChild) { public void setBiologicalChild(Child biologicalChild) {
this.ownedBidirectionalChild = ownedBidirectionalChild; this.biologicalChild = biologicalChild;
} }
public Child2 getChildMappedByParent1() { public AdoptedChild getAdopted() {
return childMappedByParent1; return adopted;
} }
public void setChildMappedByParent1(Child2 childMappedByParent1) { public void setAdopted(AdoptedChild adopted) {
this.childMappedByParent1 = childMappedByParent1; this.adopted = adopted;
} }
} }
@Entity(name = "Child") @Entity(name = "Child")
@ -318,17 +514,18 @@ public class EntityWithBidirectionalOneToOneTest {
private Integer id; private Integer id;
private String name; private String name;
@OneToOne(mappedBy = "ownedBidirectionalChild") @OneToOne(mappedBy = "biologicalChild")
private Parent parentMappedByChild; private Mother mother;
Child() { Child() {
} }
Child(Integer id, Parent parentMappedByChild) { Child(Integer id, String name, Mother mother) {
this.id = id; this.id = id;
this.parentMappedByChild = parentMappedByChild; this.name = name;
this.parentMappedByChild.setOwnedBidirectionalChild( this ); this.mother = mother;
this.mother.setBiologicalChild( this );
} }
public Integer getId() { public Integer getId() {
@ -347,39 +544,39 @@ public class EntityWithBidirectionalOneToOneTest {
this.name = name; this.name = name;
} }
public Parent getParentMappedByChild() { public Mother getMother() {
return parentMappedByChild; return mother;
} }
public void setParentMappedByChild(Parent parentMappedByChild) { public void setMother(Mother mother) {
this.parentMappedByChild = parentMappedByChild; this.mother = mother;
} }
} }
@Entity(name = "Child2") @Entity(name = "AdoptedChild")
@Table(name = "CHILD2") @Table(name = "ADOPTED_CHILD")
public static class Child2 { public static class AdoptedChild {
@Id @Id
private Integer id; private Integer id;
private String name; private String name;
@OneToOne @OneToOne
private Parent ownedBidirectionalParent; private Mother biologicalMother;
@OneToOne @OneToOne
private Parent unidirectionalParent; private Mother stepMother;
Child2() { AdoptedChild() {
} }
Child2(Integer id, Parent ownedBidirectionalParent) { AdoptedChild(Integer id, String name, Mother stepMother) {
this.id = id; this.id = id;
this.ownedBidirectionalParent = ownedBidirectionalParent; this.name = name;
this.ownedBidirectionalParent.setChildMappedByParent1( this ); this.stepMother = stepMother;
this.stepMother.setAdopted( this );
} }
public Integer getId() { public Integer getId() {
return id; return id;
} }
@ -396,20 +593,28 @@ public class EntityWithBidirectionalOneToOneTest {
this.name = name; this.name = name;
} }
public Parent getOwnedBidirectionalParent() { public Mother getBiologicalMother() {
return ownedBidirectionalParent; return biologicalMother;
} }
public void setOwnedBidirectionalParent(Parent ownedBidirectionalParent) { public void setBiologicalMother(Mother biologicalMother) {
this.ownedBidirectionalParent = ownedBidirectionalParent; this.biologicalMother = biologicalMother;
} }
public Parent getUnidirectionalParent() { public Mother getStepMother() {
return unidirectionalParent; return stepMother;
} }
public void setUnidirectionalParent(Parent parent) { public void setStepMother(Mother stepMother) {
this.unidirectionalParent = parent; this.stepMother = stepMother;
}
@Override
public String toString() {
return "AdoptedChild{" +
"id=" + id +
", name='" + name + '\'' +
'}';
} }
} }
} }

View File

@ -1,79 +0,0 @@
/*
* 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.test.annotations.cid.keymanytoone;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
/**
* @author Steve Ebersole
*/
public class EagerKeyManyToOneTest extends BaseCoreFunctionalTestCase {
public static final String CARD_ID = "cardId";
public static final String KEY_ID = "keyId";
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Card.class, CardField.class, Key.class, PrimaryKey.class };
}
@Test
@TestForIssue( jiraKey = "HHH-4147" )
public void testLoadEntityWithEagerFetchingToKeyManyToOneReferenceBackToSelf() {
// based on the core testsuite test of same name in org.hibernate.test.keymanytoone.bidir.component.EagerKeyManyToOneTest
// meant to test against regression relating to http://opensource.atlassian.com/projects/hibernate/browse/HHH-2277
// and http://opensource.atlassian.com/projects/hibernate/browse/HHH-4147
{
Session s = openSession();
s.beginTransaction();
Card card = new Card( CARD_ID );
Key key = new Key( KEY_ID );
card.addField( card, key );
s.persist( key );
s.persist( card );
s.getTransaction().commit();
s.close();
}
{
Session s = openSession();
s.beginTransaction();
try {
Card card = (Card) s.get( Card.class, CARD_ID );
assertEquals( 1, card.getFields().size() );
CardField cf = card.getFields().iterator().next();
assertSame( card, cf.getPrimaryKey().getCard() );
}
catch ( StackOverflowError soe ) {
fail( "eager + key-many-to-one caused stack-overflow in annotations" );
}
finally {
s.getTransaction().commit();
s.close();
}
}
{
Session s = openSession();
s.beginTransaction();
Card card = (Card) s.get( Card.class, CARD_ID );
Key key = (Key) s.get( Key.class, KEY_ID );
s.delete( card );
s.delete( key );
s.getTransaction().commit();
s.close();
}
}
}

View File

@ -44,12 +44,12 @@ public class SQLStatementInspector implements StatementInspector {
} }
public void assertExecutedCount(int expected) { public void assertExecutedCount(int expected) {
assertEquals( expected, sqlQueries.size() ); assertEquals( "Number of executed statements ",expected, sqlQueries.size() );
} }
public void assertNumberOfOccurrenceInQuery(int queryNumber, String toCheck, int expectedNumberOfOccurrences) { public void assertNumberOfOccurrenceInQuery(int queryNumber, String toCheck, int expectedNumberOfOccurrences) {
String query = sqlQueries.get( queryNumber ); String query = sqlQueries.get( queryNumber );
int actual = query.split( toCheck, -1 ).length - 1; int actual = query.split( " " + toCheck + " ", -1 ).length - 1;
assertThat( actual, is( expectedNumberOfOccurrences ) ); assertThat( "number of " + toCheck,actual, is( expectedNumberOfOccurrences ) );
} }
} }