HHH-13725 ToMany FkDescriptor creation and circular fetch detecion

This commit is contained in:
Andrea Boriero 2019-11-19 11:50:06 +00:00 committed by Steve Ebersole
parent aa3ff4507d
commit 343dd979ba
21 changed files with 1417 additions and 143 deletions

View File

@ -13,7 +13,7 @@ package org.hibernate.metamodel.mapping;
public interface ColumnConsumer {
// todo (6.0) : pass values `updateable`, `checkable`, etc
void accept(
String columnExpression,
String containingTableExpression,
String columnExpression,
JdbcMapping jdbcMapping);
}

View File

@ -35,4 +35,8 @@ public interface InFlightEntityMappingType extends EntityMappingType {
default void prepareMappingModel(MappingModelCreationProcess creationProcess) {
// by default do nothing - support for legacy impls
}
default void finishMappingModelInitialization(MappingModelCreationProcess creationProcess) {
// by default do nothing
}
}

View File

@ -13,13 +13,9 @@ import java.util.SortedMap;
import java.util.SortedSet;
import java.util.function.Consumer;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.SessionFactory;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
@ -911,58 +907,95 @@ public class MappingModelCreationHelper {
);
}
private static ForeignKeyDescriptor interpretKeyDescriptor(
public static void interpretKeyDescriptor(
SingularAssociationAttributeMapping attributeMapping,
Property bootProperty,
ToOne bootValueMapping,
EntityPersister referencedEntityDescriptor,
EntityPersister declaringEntityDescriptor,
Dialect dialect,
MappingModelCreationProcess creationProcess) {
if ( attributeMapping.getForeignKeyDescriptor() != null ) {
return;
}
EntityPersister referencedEntityDescriptor = creationProcess.getEntityPersister(
bootValueMapping.getReferencedEntityName() );
final ModelPart fkTarget;
final ForeignKeyDirection foreignKeyDirection = ( (AssociationType) bootValueMapping.getType() ).getForeignKeyDirection();
referencedEntityDescriptor.prepareMappingModel( creationProcess );
if ( bootValueMapping.isReferenceToPrimaryKey() ) {
referencedEntityDescriptor.prepareMappingModel( creationProcess );
fkTarget = referencedEntityDescriptor.getIdentifierMapping();
}
else {
fkTarget = referencedEntityDescriptor.findSubPart( bootValueMapping.getReferencedPropertyName() );
fkTarget = declaringEntityDescriptor.getIdentifierMapping();
}
final JdbcServices jdbcServices = creationProcess.getCreationContext().getSessionFactory().getJdbcServices();
if ( fkTarget instanceof BasicValuedModelPart ) {
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
final String keyColumnExpression;
final String keyTableIdentifierExpression;
if ( bootValueMapping.isReferenceToPrimaryKey() ) {
final Iterator<Selectable> columnIterator = bootValueMapping.getColumnIterator();
if ( columnIterator.hasNext() ) {
keyColumnExpression = columnIterator.next().getText( dialect );
}
else {
// case of ToOne with @PrimaryKeyJoinColumn
keyColumnExpression = bootValueMapping.getTable().getColumn( 0 ).getName();
}
final Iterator<Selectable> columnIterator = bootValueMapping.getColumnIterator();
String keyColumnExpression;
keyTableIdentifierExpression = creationProcess.getCreationContext()
.getBootstrapContext()
.getMetadataBuildingOptions()
.getPhysicalNamingStrategy().toPhysicalTableName(
bootValueMapping.getTable().getNameIdentifier(),
jdbcServices.getJdbcEnvironment()
).getText();
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
ForeignKeyDescriptor foreignKeyDescriptor = new SimpleForeignKeyDescriptor(
foreignKeyDirection,
keyTableIdentifierExpression,
keyColumnExpression,
simpleFkTarget.getContainingTableExpression(),
simpleFkTarget.getMappedColumnExpression(),
simpleFkTarget.getJdbcMapping()
);
attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor );
final Identifier tableIdentifier = creationProcess.getCreationContext()
.getBootstrapContext()
.getMetadataBuildingOptions()
.getPhysicalNamingStrategy().toPhysicalTableName(
bootValueMapping.getTable().getNameIdentifier(),
jdbcServices.getJdbcEnvironment()
);
if ( columnIterator.hasNext() ) {
keyColumnExpression = columnIterator.next().getText( dialect );
}
else {
// case of ToOne with @PrimaryKeyJoinColumn
keyColumnExpression = bootValueMapping.getTable().getColumn( 0 ).getName();
SingularAssociationAttributeMapping subPart = (SingularAssociationAttributeMapping) referencedEntityDescriptor
.findSubPart( bootValueMapping.getReferencedPropertyName() );
ForeignKeyDescriptor foreignKeyDescriptor = subPart.getForeignKeyDescriptor();
if ( foreignKeyDescriptor == null ) {
PersistentClass entityBinding = creationProcess.getCreationContext()
.getBootModel()
.getEntityBinding(
referencedEntityDescriptor.getEntityName() );
Property property = entityBinding.getProperty( bootValueMapping.getReferencedPropertyName() );
interpretKeyDescriptor(
subPart,
property,
(ToOne) property.getValue(),
referencedEntityDescriptor,
dialect,
creationProcess
);
attributeMapping.setForeignKeyDescriptor( subPart.getForeignKeyDescriptor() );
}
else {
attributeMapping.setForeignKeyDescriptor( foreignKeyDescriptor );
}
}
return new SimpleForeignKeyDescriptor(
((AssociationType)bootValueMapping.getType()).getForeignKeyDirection(),
tableIdentifier.getText(),
keyColumnExpression,
simpleFkTarget.getContainingTableExpression(),
simpleFkTarget.getMappedColumnExpression(),
simpleFkTarget.getJdbcMapping()
}
else {
throw new NotYetImplementedFor6Exception(
"Support for composite foreign-keys not yet implemented: " +
bootProperty.getPersistentClass().getEntityName() + " -> " + bootProperty.getName()
);
}
throw new NotYetImplementedFor6Exception(
"Support for composite foreign-keys not yet implemented: " +
bootProperty.getPersistentClass().getEntityName() + " -> " + bootProperty.getName()
);
}
private static CollectionPart interpretMapKey(
@ -1140,18 +1173,6 @@ public class MappingModelCreationHelper {
creationProcess
);
SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
final Dialect dialect = sessionFactory
.getJdbcServices()
.getJdbcEnvironment()
.getDialect();
final ForeignKeyDescriptor foreignKeyDescriptor = interpretKeyDescriptor(
bootProperty,
value,
entityPersister,
dialect,
creationProcess
);
final AssociationType type = (AssociationType) bootProperty.getType();
final FetchStyle fetchStyle = FetchStrategyHelper
@ -1168,8 +1189,7 @@ public class MappingModelCreationHelper {
return new SingularAssociationAttributeMapping(
attrName,
stateArrayPosition,
bootProperty.getValue().isNullable(),
foreignKeyDescriptor,
(ToOne) bootProperty.getValue(),
stateArrayContributorMetadataAccess,
fetchStrategy,
entityPersister,

View File

@ -7,7 +7,6 @@
package org.hibernate.metamodel.mapping.internal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -67,6 +66,12 @@ public class MappingModelCreationProcess {
entityPersister.prepareMappingModel( this );
}
for ( EntityPersister entityPersister : entityPersisterMap.values() ) {
currentlyProcessingRole = entityPersister.getEntityName();
entityPersister.finishMappingModelInitialization( this );
}
while ( postInitCallbacks != null && ! postInitCallbacks.isEmpty() ) {
// copy to avoid CCME
final ArrayList<PostInitCallback> copy = new ArrayList<>( new ArrayList<>( postInitCallbacks ) );

View File

@ -9,14 +9,12 @@ package org.hibernate.metamodel.mapping.internal;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming;
import org.hibernate.mapping.ToOne;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.NavigablePath;
@ -39,6 +37,7 @@ import org.hibernate.sql.results.internal.domain.entity.EntityFetch;
import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParent;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
@ -47,13 +46,13 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
implements EntityValuedModelPart, TableGroupJoinProducer {
private final String sqlAliasStem;
private final boolean isNullable;
private final ForeignKeyDescriptor foreignKeyDescriptor;
private ForeignKeyDescriptor foreignKeyDescriptor;
private final String referencedPropertyName;
public SingularAssociationAttributeMapping(
String name,
int stateArrayPosition,
boolean isNullable,
ForeignKeyDescriptor foreignKeyDescriptor,
ToOne value,
StateArrayContributorMetadataAccess attributeMetadataAccess,
FetchStrategy mappedFetchStrategy,
EntityMappingType type,
@ -69,10 +68,18 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
propertyAccess
);
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name );
this.isNullable = isNullable;
this.isNullable = value.isNullable();
referencedPropertyName = value.getReferencedPropertyName();
}
public void setForeignKeyDescriptor(ForeignKeyDescriptor foreignKeyDescriptor){
this.foreignKeyDescriptor = foreignKeyDescriptor;
}
public ForeignKeyDescriptor getForeignKeyDescriptor(){
return this.foreignKeyDescriptor;
}
@Override
public EntityMappingType getMappedTypeDescriptor() {
return (EntityMappingType) super.getMappedTypeDescriptor();
@ -227,38 +234,42 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
@Override
public boolean isCircular(FetchParent fetchParent, SqlAstProcessingState creationState) {
final NavigablePath navigablePath = fetchParent.getNavigablePath();
final NavigablePath parent = navigablePath.getParent();
if ( parent == null ) {
final NavigablePath panentNaviblePath = fetchParent.getNavigablePath();
final NavigablePath parentParentNavigablePath = panentNaviblePath.getParent();
if ( parentParentNavigablePath == null ) {
return false;
}
else {
final String entityName = getMappedTypeDescriptor().getEntityName();
if ( parent.getLocalName().equals( entityName ) ) {
return true;
}
else {
NavigablePath parentOfParent = parent.getParent();
if ( parentOfParent == null ) {
return false;
if ( panentNaviblePath.getLocalName().equals( referencedPropertyName ) ) {
if ( parentParentNavigablePath.getLocalName().equals( entityName ) ) {
return true;
}
else {
if ( parentOfParent.getParent() != null ) {
return false;
}
else {
final EntityPersister entityDescriptor = creationState.getSqlAstCreationState()
.getCreationContext()
.getDomainModel()
.findEntityDescriptor( parentOfParent.getFullPath() );
final String parentEntityName = entityDescriptor.findSubPart( parent.getLocalName() ).getJavaTypeDescriptor()
.getJavaType()
.getName();
if ( parentEntityName.equals( entityName ) ) {
return true;
}
// need to check if panentNaviblePath.getParent()
// FetchParent fetchParent1 = fetchParentByNavigableFullPath.get( parentParentNavigablePath.getFullPath() );
final JavaTypeDescriptor resultJavaTypeDescriptor = fetchParent.getResultJavaTypeDescriptor();
if ( getEntityMappingType().getJavaTypeDescriptor().getJavaType()
.equals( resultJavaTypeDescriptor.getJavaType() ) ) {
return true;
}
return false;
}
}
else {
if ( parentParentNavigablePath.getLocalName().equals( entityName ) ) {
return true;
}
JavaTypeDescriptor parentParentJavaTypeDescriptor = creationState.getSqlAstCreationState()
.getFromClauseAccess()
.findTableGroup( parentParentNavigablePath )
.getModelPart()
.getJavaTypeDescriptor();
if ( getEntityMappingType().getJavaTypeDescriptor().getJavaType()
.equals( parentParentJavaTypeDescriptor.getJavaType() ) ) {
return true;
}
return false;
}

View File

@ -134,6 +134,7 @@ import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.ToOne;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.mapping.AttributeMapping;
@ -143,6 +144,7 @@ import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NaturalIdMapping;
@ -153,6 +155,7 @@ import org.hibernate.metamodel.mapping.internal.EntityDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
@ -6213,6 +6216,26 @@ public abstract class AbstractEntityPersister
);
}
@Override
public void finishMappingModelInitialization(MappingModelCreationProcess creationProcess) {
singularAssociationsToFinilize.forEach( (property, singularAssociationAttributeMapping) -> {
final Dialect dialect = creationProcess.getCreationContext()
.getSessionFactory()
.getJdbcServices()
.getJdbcEnvironment()
.getDialect();
MappingModelCreationHelper.interpretKeyDescriptor(
singularAssociationAttributeMapping,
property,
(ToOne) property.getValue(),
this,
dialect,
creationProcess
);
} );
}
protected static SqmMultiTableMutationStrategy interpretSqmMultiTableStrategy(
AbstractEntityPersister entityMappingDescriptor,
MappingModelCreationProcess creationProcess) {
@ -6378,6 +6401,8 @@ public abstract class AbstractEntityPersister
throw new NotYetImplementedFor6Exception( AbstractEntityPersister.class );
}
Map<Property,SingularAssociationAttributeMapping> singularAssociationsToFinilize = new HashMap<>( );
private AttributeMapping generateNonIdAttributeMapping(
NonIdentifierAttribute tupleAttrDefinition,
Property bootProperty,
@ -6438,7 +6463,7 @@ public abstract class AbstractEntityPersister
);
}
else if ( attrType instanceof EntityType ) {
return MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
SingularAssociationAttributeMapping attributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(
attrName,
stateArrayPosition,
bootProperty,
@ -6448,6 +6473,8 @@ public abstract class AbstractEntityPersister
tupleAttrDefinition.getCascadeStyle(),
creationProcess
);
singularAssociationsToFinilize.put( bootProperty,attributeMapping );
return attributeMapping;
}
// todo (6.0) : for now ignore any non basic-typed attributes

View File

@ -19,7 +19,10 @@ import org.hibernate.sql.results.internal.domain.BiDirectionalFetchImpl;
*/
public class CircularFetchDetector {
public Fetch findBiDirectionalFetch(FetchParent fetchParent, Fetchable fetchable, SqlAstProcessingState creationState) {
public Fetch findBiDirectionalFetch(
FetchParent fetchParent,
Fetchable fetchable,
SqlAstProcessingState creationState) {
if ( !fetchable.isCircular( fetchParent, creationState ) ) {
return null;
}

View File

@ -0,0 +1,262 @@
/*
* 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.metamodel.mapping.manytoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
ManyToOneJoinTableTest.SimpleEntity.class,
ManyToOneJoinTableTest.OtherEntity.class,
ManyToOneJoinTableTest.AnotherEntity.class
}
)
@ServiceRegistry
@SessionFactory
public class ManyToOneJoinTableTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister otherDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( OtherEntity.class );
final ModelPart simpleEntityAssociation = otherDescriptor.findSubPart( "simpleEntity" );
assertThat( simpleEntityAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping simpleAttributeMapping = (SingularAssociationAttributeMapping) simpleEntityAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = simpleAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "other_simple" ) );
assertThat( keyColumn, is( "RHS_ID" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "simple_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
final ModelPart anotherEntityAssociation = otherDescriptor.findSubPart( "anotherEntity" );
assertThat( anotherEntityAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping anotherAttributeMapping = (SingularAssociationAttributeMapping) anotherEntityAssociation;
foreignKeyDescriptor = anotherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "other_another" ) );
assertThat( keyColumn, is( "RHS_ID" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "another_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
final EntityPersister simpleDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( SimpleEntity.class );
ModelPart otherEntityEntityAssociation = simpleDescriptor.findSubPart( "other" );
assertThat( otherEntityEntityAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
SingularAssociationAttributeMapping otherAttributeMapping = (SingularAssociationAttributeMapping) otherEntityEntityAssociation;
foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "other_simple" ) );
assertThat( keyColumn, is( "LHS_ID" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "other_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
final EntityPersister anotherDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( AnotherEntity.class );
otherEntityEntityAssociation = anotherDescriptor.findSubPart( "other" );
assertThat( otherEntityEntityAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
otherAttributeMapping = (SingularAssociationAttributeMapping) otherEntityEntityAssociation;
foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "another_entity" ) );
assertThat( keyColumn, is( "other_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "other_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
}
@Entity(name = "OtherEntity")
@Table(name = "other_entity")
public static class OtherEntity {
private Integer id;
private String name;
private SimpleEntity simpleEntity;
private AnotherEntity anotherEntity;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne
@JoinTable(name = "other_simple",
joinColumns = {
@JoinColumn(name = "LHS_ID")
},
inverseJoinColumns = {
@JoinColumn(name = "RHS_ID")
})
public SimpleEntity getSimpleEntity() {
return simpleEntity;
}
public void setSimpleEntity(SimpleEntity simpleEntity) {
this.simpleEntity = simpleEntity;
}
@ManyToOne
@JoinTable(name = "other_another",
joinColumns = {
@JoinColumn(name = "LHS_ID")
},
inverseJoinColumns = {
@JoinColumn(name = "RHS_ID")
})
public AnotherEntity getAnotherEntity() {
return anotherEntity;
}
public void setAnotherEntity(AnotherEntity anotherEntity) {
this.anotherEntity = anotherEntity;
}
}
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public static class SimpleEntity {
private Integer id;
private String name;
private OtherEntity other;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(mappedBy = "simpleEntity")
public OtherEntity getOther() {
return other;
}
public void setOther(OtherEntity other) {
this.other = other;
}
}
@Entity(name = "AnotherEntity")
@Table(name = "another_entity")
public static class AnotherEntity {
private Integer id;
private String name;
private OtherEntity other;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne
public OtherEntity getOther() {
return other;
}
public void setOther(OtherEntity other) {
this.other = other;
}
}
}

View File

@ -0,0 +1,130 @@
/*
* 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.metamodel.mapping.manytoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
ManyToOneTest.SimpleEntity.class,
ManyToOneTest.OtherEntity.class
}
)
@ServiceRegistry
@SessionFactory
public class ManyToOneTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister otherDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( OtherEntity.class );
final ModelPart simpleEntityAssociation = otherDescriptor.findSubPart( "simpleEntity" );
assertThat( simpleEntityAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping childAttributeMapping = (SingularAssociationAttributeMapping) simpleEntityAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = childAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "other_entity" ) );
assertThat( keyColumn, is( "simple_entity_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "simple_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
}
@Entity(name = "OtherEntity")
@Table(name = "other_entity")
public static class OtherEntity {
private Integer id;
private String name;
private SimpleEntity simpleEntity;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne
@JoinColumn(name = "simple_entity_id")
public SimpleEntity getSimpleEntity() {
return simpleEntity;
}
public void setSimpleEntity(SimpleEntity simpleEntity) {
this.simpleEntity = simpleEntity;
}
}
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public static class SimpleEntity {
private Integer id;
private String name;
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,173 @@
/*
* 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.metamodel.mapping.onetoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityWithBidirectionalAssociationTest.Parent.class,
EntityWithBidirectionalAssociationTest.Child.class
}
)
@ServiceRegistry
@SessionFactory
public class EntityWithBidirectionalAssociationTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister parentDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( Parent.class );
final ModelPart childAssociation = parentDescriptor.findSubPart( "child" );
assertThat( childAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping childAttributeMapping = (SingularAssociationAttributeMapping) childAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = childAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT" ) );
assertThat( keyColumn, is( "child_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "CHILD" ) );
assertThat( targetColumn, is( "id" ) );
} );
final EntityPersister childDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( Child.class );
final ModelPart parentAssociation = childDescriptor.findSubPart( "parent" );
assertThat( parentAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping parentAttributeMapping = (SingularAssociationAttributeMapping) parentAssociation;
foreignKeyDescriptor = parentAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT" ) );
assertThat( keyColumn, is( "child_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "CHILD" ) );
assertThat( targetColumn, is( "id" ) );
} );
}
@Entity(name = "Parent")
@Table(name = "PARENT")
public static class Parent {
private Integer id;
private String description;
private Child child;
Parent() {
}
public Parent(Integer id, String description) {
this.id = id;
this.description = description;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@OneToOne
public Child getChild() {
return child;
}
public void setChild(Child other) {
this.child = other;
}
}
@Entity(name = "Child")
@Table(name = "CHILD")
public static class Child {
private Integer id;
private String name;
private Parent parent;
Child() {
}
Child(Integer id, Parent parent) {
this.id = id;
this.parent = parent;
this.parent.setChild( this );
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(mappedBy = "child")
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
}

View File

@ -0,0 +1,177 @@
/*
* 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.metamodel.mapping.onetoone;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityWithOneBidirectionalJoinTableAssociationTest.Parent.class,
EntityWithOneBidirectionalJoinTableAssociationTest.Child.class,
}
)
@ServiceRegistry
@SessionFactory
public class EntityWithOneBidirectionalJoinTableAssociationTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister parentDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( Parent.class );
final ModelPart childAssociation = parentDescriptor.findSubPart( "child" );
assertThat( childAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping childAttributeMapping = (SingularAssociationAttributeMapping) childAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = childAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT_CHILD" ) );
assertThat( keyColumn, is( "child_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "CHILD" ) );
assertThat( targetColumn, is( "id" ) );
} );
final EntityPersister childDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( Child.class );
final ModelPart parentAssociation = childDescriptor.findSubPart( "parent" );
assertThat( parentAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping parentAttributeMapping = (SingularAssociationAttributeMapping) parentAssociation;
foreignKeyDescriptor = parentAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT_CHILD" ) );
assertThat( keyColumn, is( "parent_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "PARENT" ) );
assertThat( targetColumn, is( "id" ) );
} );
}
@Entity(name = "Parent")
@Table(name = "PARENT")
public static class Parent {
private Integer id;
private String description;
private Child child;
Parent() {
}
public Parent(Integer id, String description) {
this.id = id;
this.description = description;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@OneToOne
@JoinTable(name = "PARENT_CHILD", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id"))
public Child getChild() {
return child;
}
public void setChild(Child other) {
this.child = other;
}
}
@Entity(name = "Child")
@Table(name = "CHILD")
public static class Child {
private Integer id;
private String name;
private Parent parent;
Child() {
}
Child(Integer id, Parent parent) {
this.id = id;
this.parent = parent;
this.parent.setChild( this );
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(mappedBy = "child")
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.metamodel.mapping.onetoone;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.domain.gambit.EntityWithOneToOneJoinTable;
import org.hibernate.testing.orm.domain.gambit.SimpleEntity;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityWithOneToOneJoinTable.class,
SimpleEntity.class
}
)
@ServiceRegistry
@SessionFactory
public class EntityWithOneToOneJoinTableTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister entityWithOneToOneJoinTableDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( EntityWithOneToOneJoinTable.class );
final ModelPart other = entityWithOneToOneJoinTableDescriptor.findSubPart( "other" );
assertThat( other, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping otherAttributeMapping = (SingularAssociationAttributeMapping) other;
final ForeignKeyDescriptor foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "Entity_SimpleEntity" ) );
assertThat( keyColumn, is( "other_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "SIMPLE_ENTITY" ) );
assertThat( targetColumn, is( "id" ) );
} );
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.metamodel.mapping.onetoone;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.orm.domain.gambit.EntityWithOneToOneSharingPrimaryKey;
import org.hibernate.testing.orm.domain.gambit.SimpleEntity;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityWithOneToOneSharingPrimaryKey.class,
SimpleEntity.class
}
)
@ServiceRegistry
@SessionFactory
public class EntityWithOneToOneSharingPrimaryKeyTest {
@Test
public void basicTest(SessionFactoryScope scope) {
final EntityPersister entityDescriptor = scope.getSessionFactory()
.getMetamodel()
.findEntityDescriptor( EntityWithOneToOneSharingPrimaryKey.class );
final ModelPart otherAssociation = entityDescriptor.findSubPart( "other" );
assertThat( otherAssociation, instanceOf( SingularAssociationAttributeMapping.class ) );
final SingularAssociationAttributeMapping otherAttributeMapping = (SingularAssociationAttributeMapping) otherAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
assertThat( keyTable, is( "EntityWithOneToOneSharingPrimaryKey" ) );
assertThat( keyColumn, is( "id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
assertThat( targetTable, is( "SIMPLE_ENTITY" ) );
assertThat( targetColumn, is( "id" ) );
} );
}
}

View File

@ -9,6 +9,8 @@ package org.hibernate.orm.test.sql.exec.manytoone;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

View File

@ -34,14 +34,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
@DomainModel(
annotatedClasses = {
EntityWithBidirectionalOneToOneJoinTableTest.Parent.class,
EntityWithBidirectionalOneToOneJoinTableTest.Child.class,
EntityWithBidirectionalOneToOneJoinTableTest.Child2.class,
EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Parent.class,
EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Child.class,
EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.Child2.class,
}
)
@ServiceRegistry
@SessionFactory(generateStatistics = true)
public class EntityWithBidirectionalOneToOneJoinTableTest {
public class EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
@ -232,7 +232,6 @@ public class EntityWithBidirectionalOneToOneJoinTableTest {
}
@OneToOne
@JoinTable(name = "PARENT_CHILD2", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id"))
public Child2 getChild2() {
return child2;
}

View File

@ -12,25 +12,21 @@ import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.boot.MetadataSources;
import org.hibernate.testing.junit5.SessionFactoryBasedFunctionalTest;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Chris Cranford
*/
@Disabled(value = "Composite FK not yet supported")
public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunctionalTest {
@Override
@ -59,9 +55,9 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
@AfterEach
public void tearDown() {
inTransaction( session -> {
session.createQuery( "delete from Child" ).executeUpdate();
session.createQuery( "delete from Child2" ).executeUpdate();
session.createQuery( "delete from Parent" ).executeUpdate();
session.createQuery( "delete from Child" ).executeUpdate();
} );
}
@ -70,23 +66,23 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
inTransaction( session -> {
final Parent parent = session.get( Parent.class, 1 );
Child child = parent.getChild();
assertThat( child, CoreMatchers.notNullValue() );
assertThat( child, notNullValue() );
assertTrue(
Hibernate.isInitialized( child ),
"The child eager OneToOne association is not initialized"
);
assertThat( child.getName(), CoreMatchers.notNullValue() );
assertThat( child.getParent(), CoreMatchers.notNullValue() );
assertThat( child.getParent(), CoreMatchers.notNullValue() );
assertThat( child.getName(), notNullValue() );
assertThat( child.getParent(), notNullValue() );
assertThat( child.getParent(), notNullValue() );
Child2 child2 = parent.getChild2();
assertThat( child2, CoreMatchers.notNullValue() );
assertThat( child2, notNullValue() );
assertTrue(
Hibernate.isInitialized( child2 ),
"The child2 eager OneToOne association is not initialized"
);
assertThat( child2.getName(), equalTo( "Fab" ) );
assertThat( child2.getParent(), CoreMatchers.notNullValue() );
assertThat( child2.getParent1(), notNullValue() );
} );
}
@ -111,33 +107,34 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
inTransaction( session -> {
final Parent parent = session.get( Parent.class, 4 );
Child child = parent.getChild();
assertThat( child, CoreMatchers.notNullValue() );
assertThat( child, notNullValue() );
assertTrue(
Hibernate.isInitialized( child ),
"The child eager OneToOne association is not initialized"
);
assertThat( child.getName(), CoreMatchers.notNullValue() );
assertThat( child.getParent(), CoreMatchers.notNullValue() );
assertThat( child.getName(), notNullValue() );
assertThat( child.getParent(), notNullValue() );
Child2 child2 = parent.getChild2();
assertThat( child2, CoreMatchers.notNullValue() );
assertThat( child2, notNullValue() );
assertTrue(
Hibernate.isInitialized( child2 ),
"The child2 eager OneToOne association is not initialized"
);
assertThat( child2.getName(), equalTo( "Fab2" ) );
assertThat( child2.getParent(), CoreMatchers.notNullValue() );
assertThat( child2.getParent().getDescription(), equalTo( "Hibernate OGM" ) );
assertThat( child2.getParent1(), notNullValue() );
assertThat( child2.getParent1().getDescription(), equalTo( "Hibernate OGM" ) );
Parent parent2 = child2.getParent2();
assertThat( parent2, CoreMatchers.notNullValue() );
assertThat( parent2, notNullValue() );
assertThat( parent2.getDescription(), equalTo( "Hibernate OGM" ) );
assertThat( parent2.getChild(), CoreMatchers.notNullValue() );
assertThat( parent2.getChild(), notNullValue() );
} );
}
@Test
@FailureExpected
public void testGetParent3() {
inTransaction( session -> {
@ -164,28 +161,28 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
assertThat( parent.getDescription(), equalTo( "Hibernate Search" ) );
Child child = parent.getChild();
assertThat( child, CoreMatchers.notNullValue() );
assertThat( child, notNullValue() );
assertTrue(
Hibernate.isInitialized( child ),
"The child eager OneToOne association is not initialized"
);
assertThat( child.getName(), CoreMatchers.notNullValue() );
assertThat( child.getParent(), CoreMatchers.notNullValue() );
assertThat( child.getName(), notNullValue() );
assertThat( child.getParent(), notNullValue() );
Child2 child2 = parent.getChild2();
assertThat( child2, CoreMatchers.notNullValue() );
assertThat( child2, notNullValue() );
assertTrue(
Hibernate.isInitialized( child2 ),
"The child2 eager OneToOne association is not initialized"
);
assertThat( child2.getName(), equalTo( "Fab2" ) );
assertThat( child2.getParent(), CoreMatchers.notNullValue() );
assertThat( child2.getParent().getDescription(), equalTo( "Hibernate Search" ) );
assertThat( child2.getParent1(), notNullValue() );
assertThat( child2.getParent1().getDescription(), equalTo( "Hibernate Search" ) );
Parent parent2 = child2.getParent2();
assertThat( parent2, CoreMatchers.notNullValue() );
assertThat( parent2, notNullValue() );
assertThat( parent2.getDescription(), equalTo( "Hibernate OGM" ) );
assertThat( parent2.getChild(), CoreMatchers.notNullValue() );
assertThat( parent2.getChild(), notNullValue() );
} );
}
@ -199,25 +196,27 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
Hibernate.isInitialized( parent ),
"The parent eager OneToOne association is not initialized"
);
assertThat( parent, CoreMatchers.notNullValue() );
assertThat( parent.getDescription(), CoreMatchers.notNullValue() );
assertThat( parent, notNullValue() );
assertThat( parent.getDescription(), notNullValue() );
Child child1 = parent.getChild();
assertThat( child1, CoreMatchers.notNullValue() );
assertThat( child1, notNullValue() );
assertTrue(
Hibernate.isInitialized( child1 ),
"The child eager OneToOne association is not initialized"
);
Child2 child2 = parent.getChild2();
assertThat( child2, CoreMatchers.notNullValue() );
assertThat( child2, notNullValue() );
assertTrue(
Hibernate.isInitialized( child2 ),
"The child2 eager OneToOne association is not initialized"
);
assertThat( child2.getParent(), CoreMatchers.notNullValue() );
assertThat( child2.getParent1(), notNullValue() );
assertThat( child2.getParent2(), notNullValue() );
} );
}
@Test
@FailureExpected
public void testHqlSelectParent() {
inTransaction(
session -> {
@ -228,14 +227,15 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
.setParameter( "id", 1 )
.getSingleResult();
assertThat( parent.getChild(), CoreMatchers.notNullValue() );
assertThat( parent.getChild(), notNullValue() );
String name = parent.getChild().getName();
assertThat( name, CoreMatchers.notNullValue() );
assertThat( name, notNullValue() );
}
);
}
@Test
@FailureExpected
public void testHqlSelectChild() {
inTransaction(
session -> {
@ -244,10 +244,10 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
.setParameter( "id", 1 )
.getSingleResult();
assertThat( child.getParent(), CoreMatchers.notNullValue() );
assertThat( child.getParent(), notNullValue() );
String description = child.getParent().getDescription();
assertThat( description, CoreMatchers.notNullValue() );
assertThat( description, notNullValue() );
}
);
}
@ -257,9 +257,9 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
@Id
private Integer id;
private String description;
@OneToOne(mappedBy = "parent")
@OneToOne
private Child child;
@OneToOne(mappedBy = "parent")
@OneToOne(mappedBy = "parent1")
private Child2 child2;
Parent() {
@ -313,7 +313,8 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
@Id
private Integer id;
private String name;
@OneToOne
@OneToOne(mappedBy = "child")
private Parent parent;
Child() {
@ -360,7 +361,7 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
private String name;
@OneToOne
private Parent parent;
private Parent parent1;
@OneToOne
private Parent parent2;
@ -368,10 +369,10 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
Child2() {
}
Child2(Integer id, Parent parent) {
Child2(Integer id, Parent parent1) {
this.id = id;
this.parent = parent;
this.parent.setChild2( this );
this.parent1 = parent1;
this.parent1.setChild2( this );
}
@ -391,12 +392,12 @@ public class EntityWithBidirectionalOneToOneTest extends SessionFactoryBasedFunc
this.name = name;
}
public Parent getParent() {
return parent;
public Parent getParent1() {
return parent1;
}
public void setParent(Parent parent) {
this.parent = parent;
public void setParent1(Parent parent1) {
this.parent1 = parent1;
}
public Parent getParent2() {

View File

@ -34,13 +34,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
@DomainModel(
annotatedClasses = {
EntityWithOneBidirectionalOneToOneJoinTableTest.Parent.class,
EntityWithOneBidirectionalOneToOneJoinTableTest.Child.class,
EntityWithOneBidirectionalJoinTableAssociationTest.Parent.class,
EntityWithOneBidirectionalJoinTableAssociationTest.Child.class,
}
)
@ServiceRegistry
@SessionFactory(generateStatistics = true)
public class EntityWithOneBidirectionalOneToOneJoinTableTest {
public class EntityWithOneBidirectionalJoinTableAssociationTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {

View File

@ -0,0 +1,332 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.sql.exec.onetoone.bidirectional;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
EntityWithTwoBidirectionalAssociationsOneWithJoinTableTest.Parent.class,
EntityWithTwoBidirectionalAssociationsOneWithJoinTableTest.Child.class,
EntityWithTwoBidirectionalAssociationsOneWithJoinTableTest.Child2.class,
}
)
@ServiceRegistry
@SessionFactory(generateStatistics = true)
public class EntityWithTwoBidirectionalAssociationsOneWithJoinTableTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Parent parent = new Parent( 1, "Hibernate" );
Child child = new Child( 2, parent );
child.setName( "Acme" );
Child2 child2 = new Child2( 3, parent );
child2.setName( "Fab" );
session.save( parent );
session.save( child );
session.save( child2 );
} );
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from Parent" ).executeUpdate();
session.createQuery( "delete from Child" ).executeUpdate();
session.createQuery( "delete from Child2" ).executeUpdate();
} );
}
@Test
public void testGetParent(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final Parent parent = session.get( Parent.class, 1 );
Child child = parent.getChild();
assertThat( child, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( child ),
"The child eager OneToOne association is not initialized"
);
assertThat( child.getName(), equalTo( "Acme" ) );
assertThat( child.getParent(), CoreMatchers.notNullValue() );
Child2 child2 = parent.getChild2();
assertThat( child2, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( child2 ),
"The child2 eager OneToOne association is not initialized"
);
assertThat( child2.getName(), equalTo( "Fab" ) );
assertThat( child2.getParent(), CoreMatchers.notNullValue() );
} );
}
@Test
public void testGetChild(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Child child = session.get( Child.class, 2 );
Parent parent = child.getParent();
assertThat( parent, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( parent ),
"The parent eager OneToOne association is not initialized"
);
assertThat( parent.getDescription(), CoreMatchers.notNullValue() );
Child child1 = parent.getChild();
assertThat( child1, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( child1 ),
"The child eager OneToOne association is not initialized"
);
Child2 child2 = parent.getChild2();
assertThat( child2, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( child2 ),
"The child2 eager OneToOne association is not initialized"
);
assertThat( child2.getParent(), CoreMatchers.notNullValue() );
} );
}
@Test
public void testHqlSelectChild(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final String queryString = "SELECT c FROM Child c JOIN c.parent d WHERE d.id = :id";
final Child child = session.createQuery( queryString, Child.class )
.setParameter( "id", 1 )
.getSingleResult();
assertThat( child.getParent(), CoreMatchers.notNullValue() );
String description = child.getParent().getDescription();
assertThat( description, CoreMatchers.notNullValue() );
}
);
}
@Test
public void testHqlSelectParent(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final Parent parent = session.createQuery(
"SELECT p FROM Parent p JOIN p.child WHERE p.id = :id",
Parent.class
)
.setParameter( "id", 1 )
.getSingleResult();
Child child = parent.getChild();
assertThat( child, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( child ),
"the child have to be initialized"
);
String name = child.getName();
assertThat( name, CoreMatchers.notNullValue() );
}
);
scope.inTransaction(
session -> {
final Parent parent = session.createQuery(
"SELECT p FROM Parent p JOIN p.child WHERE p.id = :id",
Parent.class
)
.setParameter( "id", 1 )
.getSingleResult();
Child child = parent.getChild();
assertThat( child, CoreMatchers.notNullValue() );
assertTrue(
Hibernate.isInitialized( child ),
"The child have to be initialized"
);
String name = child.getName();
assertThat( name, CoreMatchers.notNullValue() );
}
);
}
@Entity(name = "Parent")
@Table(name = "PARENT")
public static class Parent {
private Integer id;
private String description;
private Child child;
private Child2 child2;
Parent() {
}
public Parent(Integer id, String description) {
this.id = id;
this.description = description;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@OneToOne
@JoinTable(name = "PARENT_CHILD", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id"))
public Child getChild() {
return child;
}
public void setChild(Child other) {
this.child = other;
}
@OneToOne
@JoinTable(name = "PARENT_CHILD_2", inverseJoinColumns = @JoinColumn(name = "child_id"), joinColumns = @JoinColumn(name = "parent_id"))
public Child2 getChild2() {
return child2;
}
public void setChild2(Child2 child2) {
this.child2 = child2;
}
}
@Entity(name = "Child")
@Table(name = "CHILD")
public static class Child {
private Integer id;
private String name;
private Parent parent;
Child() {
}
Child(Integer id, Parent parent) {
this.id = id;
this.parent = parent;
this.parent.setChild( this );
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(mappedBy = "child")
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
@Entity(name = "Child2")
@Table(name = "CHILD2")
public static class Child2 {
private Integer id;
private String name;
private Parent parent;
Child2() {
}
Child2(Integer id, Parent child) {
this.id = id;
this.parent = child;
this.parent.setChild2( this );
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(mappedBy = "child2")
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
}

View File

@ -10,11 +10,13 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;
/**
* @author Andrea Boriero
*/
@Entity
@Table(name = "EntityWithOneToOneJoinTable")
public class EntityWithOneToOneJoinTable {
private Integer id;

View File

@ -10,11 +10,13 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
/**
* @author Andrea Boriero
*/
@Entity
@Table(name= "EntityWithOneToOneSharingPrimaryKey")
public class EntityWithOneToOneSharingPrimaryKey {
private Integer id;

View File

@ -10,6 +10,7 @@ import java.time.Instant;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@ -19,6 +20,7 @@ import org.hibernate.annotations.NaturalId;
* @author Steve Ebersole
*/
@Entity
@Table(name = "SIMPLE_ENTITY")
public class SimpleEntity {
private Integer id;