Fix ToOne @Fetch(FetchMode.SELECT)

This commit is contained in:
Andrea Boriero 2020-03-20 12:37:25 +00:00
parent 8971843626
commit 2f98e4bfe8
7 changed files with 1709 additions and 61 deletions

View File

@ -34,6 +34,7 @@ import org.hibernate.mapping.Component;
import org.hibernate.mapping.IndexedCollection;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
@ -1041,59 +1042,72 @@ public class MappingModelCreationHelper {
PropertyAccess propertyAccess,
CascadeStyle cascadeStyle,
MappingModelCreationProcess creationProcess) {
ToOne value = (ToOne) bootProperty.getValue();
final EntityPersister entityPersister = creationProcess.getEntityPersister( value.getReferencedEntityName() );
if ( bootProperty.getValue() instanceof ToOne ) {
final ToOne value = (ToOne) bootProperty.getValue();
final EntityPersister entityPersister = creationProcess.getEntityPersister( value.getReferencedEntityName() );
final StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess = getStateArrayContributorMetadataAccess(
bootProperty,
attrType,
propertyAccess,
cascadeStyle,
creationProcess
);
SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
final StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess = getStateArrayContributorMetadataAccess(
bootProperty,
attrType,
propertyAccess,
cascadeStyle,
creationProcess
);
SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
final AssociationType type = (AssociationType) bootProperty.getType();
final FetchStyle fetchStyle = FetchStrategyHelper
.determineFetchStyleByMetadata(
bootProperty.getValue().getFetchMode(),
type,
sessionFactory
);
final FetchTiming fetchTiming = FetchStrategyHelper.determineFetchTiming( fetchStyle, type, sessionFactory );
final FetchStrategy fetchStrategy = new FetchStrategy( fetchTiming, fetchStyle );
final SingularAssociationAttributeMapping attributeMapping = new SingularAssociationAttributeMapping(
attrName,
stateArrayPosition,
(ToOne) bootProperty.getValue(),
stateArrayContributorMetadataAccess,
fetchStrategy,
entityPersister,
declaringType,
propertyAccess
);
creationProcess.registerInitializationCallback(
() -> {
final Dialect dialect = creationProcess.getCreationContext()
.getSessionFactory()
.getJdbcServices()
.getDialect();
MappingModelCreationHelper.interpretKeyDescriptor(
attributeMapping,
bootProperty,
(ToOne) bootProperty.getValue(),
declaringType.findContainingEntityMapping(),
dialect,
creationProcess
final AssociationType type = (AssociationType) bootProperty.getType();
final FetchStyle fetchStyle = FetchStrategyHelper
.determineFetchStyleByMetadata(
bootProperty.getValue().getFetchMode(),
type,
sessionFactory
);
return true;
}
);
return attributeMapping;
}
final FetchTiming fetchTiming;
if ( fetchStyle == fetchStyle.JOIN
|| ( value instanceof OneToOne && value.isNullable() )
|| !( value ).isLazy() ) {
fetchTiming = FetchTiming.IMMEDIATE;
}
else {
fetchTiming = FetchStrategyHelper.determineFetchTiming( fetchStyle, type, sessionFactory );
}
final FetchStrategy fetchStrategy = new FetchStrategy( fetchTiming, fetchStyle );
final SingularAssociationAttributeMapping attributeMapping = new SingularAssociationAttributeMapping(
attrName,
stateArrayPosition,
(ToOne) bootProperty.getValue(),
stateArrayContributorMetadataAccess,
fetchStrategy,
entityPersister,
declaringType,
propertyAccess
);
creationProcess.registerInitializationCallback(
() -> {
final Dialect dialect = creationProcess.getCreationContext()
.getSessionFactory()
.getJdbcServices()
.getDialect();
MappingModelCreationHelper.interpretKeyDescriptor(
attributeMapping,
bootProperty,
(ToOne) bootProperty.getValue(),
declaringType.findContainingEntityMapping(),
dialect,
creationProcess
);
return true;
}
);
return attributeMapping;
}
else {
throw new NotYetImplementedFor6Exception( "AnyType support has not yet been implemented" );
}
}
}

View File

@ -15,7 +15,6 @@ import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.ToOne;
import org.hibernate.persister.collection.AbstractCollectionPersister;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
@ -120,14 +119,6 @@ public final class FetchStrategyHelper {
FetchStyle style,
AssociationType type,
SessionFactoryImplementor sessionFactory) {
if ( type instanceof ToOne ) {
if ( ( (ToOne) type ).isLazy() ) {
return FetchTiming.DELAYED;
}
else {
return FetchTiming.IMMEDIATE;
}
}
switch ( style ) {
case JOIN: {
return FetchTiming.IMMEDIATE;

View File

@ -0,0 +1,364 @@
/*
* 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>.
*/
/*
* 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.fetchmode.toone;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
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.SessionFactoryProducer;
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.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
@DomainModel(
annotatedClasses = {
EagerToOneWithJoinFetchModeTests.RootEntity.class,
EagerToOneWithJoinFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@ServiceRegistry(
settings = {
@ServiceRegistry.Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
SimpleEntity manyToOneSimpleEntity = new SimpleEntity( 1, "manyToOne" );
SimpleEntity oneToOneSimpleEntity = new SimpleEntity( 2, "oneToOne" );
session.save( manyToOneSimpleEntity );
session.save( oneToOneSimpleEntity );
RootEntity rootEntity = new RootEntity( 1, "root" );
rootEntity.manyToOneSimpleEntity = manyToOneSimpleEntity;
rootEntity.oneToOneSimpleEntity = oneToOneSimpleEntity;
session.save( rootEntity );
} );
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.createQuery( "delete from RootEntity" ).executeUpdate();
session.createQuery( "delete from SimpleEntity" ).executeUpdate();
} );
}
@Test
public void testFind(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.find( RootEntity.class, 1 );
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String executedStatement = sqls.get( 0 );
assertThat( executedStatement, containsString( " root_entity " ) );
assertThat( executedStatement, containsString( " left outer join simple_entity " ) );
assertThat(
executedStatement.replaceFirst( "left outer join", "" ),
containsString( " left outer join " )
);
assertThat(
executedStatement.replaceFirst( " left outer join", "" )
.replaceFirst( "left outer join", "" ),
not( containsString( " join " ) )
);
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 0 ), containsString( " root_entity " ) );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 2 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 2 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.manyToOneSimpleEntity join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( "inner join", "" )
.replaceFirst( "inner join", "" )
,
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
}
);
}
@Entity(name = "RootEntity")
@Table(name = "root_entity")
public static class RootEntity {
@Id
private Integer id;
private String name;
@ManyToOne
@Fetch(FetchMode.JOIN)
private SimpleEntity manyToOneSimpleEntity;
@OneToOne
@Fetch(FetchMode.JOIN)
private SimpleEntity oneToOneSimpleEntity;
public RootEntity() {
}
public RootEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public static class SimpleEntity {
@Id
private Integer id;
private String name;
public SimpleEntity() {
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,389 @@
/*
* 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.fetchmode.toone;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
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.SessionFactoryProducer;
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.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
/**
* @author Nathan Xu
*/
@DomainModel(
annotatedClasses = {
EagerToOneWithSelectFetchModeTests.RootEntity.class,
EagerToOneWithSelectFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@ServiceRegistry(
settings = {
@ServiceRegistry.Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
SimpleEntity manyToOneSimpleEntity = new SimpleEntity( 1, "manyToOne" );
SimpleEntity oneToOneSimpleEntity = new SimpleEntity( 2, "oneToOne" );
session.save( manyToOneSimpleEntity );
session.save( oneToOneSimpleEntity );
RootEntity rootEntity = new RootEntity( 1, "root" );
rootEntity.manyToOneSimpleEntity = manyToOneSimpleEntity;
rootEntity.oneToOneSimpleEntity = oneToOneSimpleEntity;
session.save( rootEntity );
} );
}
@Test
public void testFind(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.find( RootEntity.class, 1 );
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 0 ), containsString( " root_entity " ) );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, not( containsString( " join " ) ) );
assertThat( firstStatement, containsString( " root_entity " ) );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 2 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join r.manyToOneSimpleEntity join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( "inner join", "" )
.replaceFirst( "inner join", "" )
,
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 2 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( " inner join ", "" )
.replaceFirst( " inner join ", "" ),
not( containsString( " join " ) )
);
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.createQuery( "delete from RootEntity" ).executeUpdate();
session.createQuery( "delete from SimpleEntity" ).executeUpdate();
} );
}
@Entity(name = "RootEntity")
@Table(name = "root_entity")
public static class RootEntity {
@Id
private Integer id;
private String name;
@ManyToOne
@Fetch(FetchMode.SELECT)
private SimpleEntity manyToOneSimpleEntity;
@OneToOne
@Fetch(FetchMode.SELECT)
private SimpleEntity oneToOneSimpleEntity;
public RootEntity() {
}
public RootEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public static class SimpleEntity {
@Id
private Integer id;
private String name;
public SimpleEntity() {
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,400 @@
/*
* 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.fetchmode.toone;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
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.SessionFactoryProducer;
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.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
/**
* @author Nathan Xu
*/
@DomainModel(
annotatedClasses = {
LazyToOneWithJoinFetchModeTests.RootEntity.class,
LazyToOneWithJoinFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@ServiceRegistry(
settings = {
@ServiceRegistry.Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
SimpleEntity manyToOneSimpleEntity = new SimpleEntity( 1, "manyToOne" );
SimpleEntity oneToOneSimpleEntity = new SimpleEntity( 2, "oneToOne" );
session.save( manyToOneSimpleEntity );
session.save( oneToOneSimpleEntity );
RootEntity rootEntity = new RootEntity( 1, "root" );
rootEntity.manyToOneSimpleEntity = manyToOneSimpleEntity;
rootEntity.oneToOneSimpleEntity = oneToOneSimpleEntity;
session.save( rootEntity );
} );
}
@Test
public void testFind(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.find( RootEntity.class, 1 );
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String executedStatement = sqls.get( 0 );
assertThat( executedStatement, containsString( " root_entity " ) );
assertThat( executedStatement, containsString( " left outer join simple_entity " ) );
assertThat(
executedStatement.replaceFirst( "left outer join", "" ),
containsString( " left outer join " )
);
assertThat(
executedStatement.replaceFirst( " left outer join", "" )
.replaceFirst( "left outer join", "" ),
not( containsString( " join " ) )
);
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, not( containsString( " join " ) ) );
assertThat( firstStatement, containsString( " root_entity " ) );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 2 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join r.manyToOneSimpleEntity join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 3 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( "inner join", "" )
.replaceFirst( "inner join", "" )
,
not( containsString( " join " ) )
);
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 2 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
}
);
}
@Test
public void testHqlJoinFetchManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( " inner join ", "" )
.replaceFirst( " inner join ", "" ),
not( containsString( " join " ) )
);
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.createQuery( "delete from RootEntity" ).executeUpdate();
session.createQuery( "delete from SimpleEntity" ).executeUpdate();
} );
}
@Entity(name = "RootEntity")
@Table(name = "root_entity")
public static class RootEntity {
@Id
private Integer id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@Fetch(FetchMode.JOIN)
private SimpleEntity manyToOneSimpleEntity;
@OneToOne(fetch = FetchType.LAZY)
@Fetch(FetchMode.JOIN)
private SimpleEntity oneToOneSimpleEntity;
public RootEntity() {
}
public RootEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public static class SimpleEntity {
@Id
private Integer id;
private String name;
public SimpleEntity() {
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,352 @@
/*
* 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.fetchmode.toone;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
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.SessionFactoryProducer;
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.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
/**
* @author Nathan Xu
*/
@DomainModel(
annotatedClasses = {
LazyToOneWithSelectFetchModeTests.RootEntity.class,
LazyToOneWithSelectFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@ServiceRegistry(
settings = {
@ServiceRegistry.Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
SimpleEntity manyToOneSimpleEntity = new SimpleEntity( 1, "manyToOne" );
SimpleEntity oneToOneSimpleEntity = new SimpleEntity( 2, "oneToOne" );
session.save( manyToOneSimpleEntity );
session.save( oneToOneSimpleEntity );
RootEntity rootEntity = new RootEntity( 1, "root" );
rootEntity.manyToOneSimpleEntity = manyToOneSimpleEntity;
rootEntity.oneToOneSimpleEntity = oneToOneSimpleEntity;
session.save( rootEntity );
} );
}
@Test
public void testFind(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.find( RootEntity.class, 1 );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls, hasSize( 1 ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"select r from RootEntity r join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join r.manyToOneSimpleEntity join r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
containsString( " join " )
);
assertThat(
firstStatement.replaceFirst( " join ", "" ).replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
}
);
}
@Test
public void testHqlJoinFetchManyToOneAndOneToOne(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( " inner join ", "" )
.replaceFirst( " inner join ", "" ),
not( containsString( " join " ) )
);
}
);
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.createQuery( "delete from RootEntity" ).executeUpdate();
session.createQuery( "delete from SimpleEntity" ).executeUpdate();
} );
}
@Entity(name = "RootEntity")
@Table(name = "root_entity")
public static class RootEntity {
@Id
private Integer id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@Fetch(FetchMode.SELECT)
private SimpleEntity manyToOneSimpleEntity;
@OneToOne(fetch = FetchType.LAZY)
@Fetch(FetchMode.SELECT)
private SimpleEntity oneToOneSimpleEntity;
public RootEntity() {
}
public RootEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public static class SimpleEntity {
@Id
private Integer id;
private String name;
public SimpleEntity() {
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,138 @@
/*
* 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>.
*/
/*
* 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.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import org.hibernate.Hibernate;
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.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Andrea Boriero
*/
@DomainModel(
annotatedClasses = {
OneToOneLazy.Title.class,
OneToOneLazy.Book.class
}
)
@SessionFactory
public class OneToOneLazy {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
sesison -> {
Title title = new Title( 1L );
Book book = new Book( 2L, title );
sesison.save( title );
sesison.save( book );
}
);
}
@Test
public void testLazyLoading(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Book book = session.find( Book.class, 2L );
assertThat( Hibernate.isInitialized( book.getTitle() ), is( false ) );
}
);
scope.inTransaction(
session -> {
Title title = session.find( Title.class, 1L );
assertThat( Hibernate.isInitialized( title.getBook() ), is( true ) );
}
);
}
@Entity
public static class Book {
@Id
private Long id;
@OneToOne(fetch = FetchType.LAZY)
private Title title;
public Book() {
}
public Book(Long id, Title title) {
this.id = id;
this.title = title;
title.setBook( this );
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Title getTitle() {
return title;
}
}
@Entity
public static class Title {
@Id
private Long id;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "title")
private Book book;
public Title() {
}
public Title(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
}
}