Fix extra query executed for Embedded fk when embeddable has a lazy ToOne association
This commit is contained in:
parent
99778fd9a1
commit
8d026b05d2
|
@ -12,6 +12,7 @@ import java.util.function.Consumer;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.ManagedEntity;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
@ -26,6 +27,7 @@ import org.hibernate.metamodel.mapping.MappingType;
|
|||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
|
@ -88,6 +90,9 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
|
|||
|
||||
@Override
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
if ( entity instanceof HibernateProxy ) {
|
||||
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier();
|
||||
}
|
||||
return propertyAccess.getGetter().get( entity );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
|||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
|
@ -113,6 +114,9 @@ public class EmbeddedIdentifierMappingImpl implements CompositeIdentifierMapping
|
|||
|
||||
@Override
|
||||
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
|
||||
if ( entity instanceof HibernateProxy ) {
|
||||
return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier();
|
||||
}
|
||||
return propertyAccess.getGetter().get( entity );
|
||||
}
|
||||
|
||||
|
|
|
@ -318,9 +318,6 @@ public class SqmUtil {
|
|||
|
||||
// assume we have (or can create) a mapping for the parameter's Java type
|
||||
BasicType basicType = typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() );
|
||||
if ( basicType == null ) {
|
||||
return StandardBasicTypes.SERIALIZABLE;
|
||||
}
|
||||
return basicType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.sql.results.graph.Initializer;
|
|||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityFetchDelayedImpl;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityFetchSelectImpl;
|
||||
|
||||
/**
|
||||
|
@ -74,15 +75,28 @@ public class EmbeddableForeignKeyResultImpl<T> extends AbstractFetchParent
|
|||
null,
|
||||
associatedEntityMappingType.getIdentifierMapping().getJavaTypeDescriptor()
|
||||
);
|
||||
Fetch fetch = new EntityFetchSelectImpl(
|
||||
this,
|
||||
singularAssociationAttributeMapping,
|
||||
null,
|
||||
false,
|
||||
navigablePath.append( fetchable.getFetchableName() ),
|
||||
domainResult,
|
||||
creationState
|
||||
);
|
||||
Fetch fetch;
|
||||
if ( singularAssociationAttributeMapping.getMappedFetchStrategy().getTiming() == FetchTiming.DELAYED ) {
|
||||
fetch = new EntityFetchDelayedImpl(
|
||||
this,
|
||||
singularAssociationAttributeMapping,
|
||||
null,
|
||||
false,
|
||||
navigablePath.append( fetchable.getFetchableName() ),
|
||||
domainResult
|
||||
);
|
||||
}
|
||||
else {
|
||||
fetch = new EntityFetchSelectImpl(
|
||||
this,
|
||||
singularAssociationAttributeMapping,
|
||||
null,
|
||||
false,
|
||||
navigablePath.append( fetchable.getFetchableName() ),
|
||||
domainResult,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* 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.compositefk;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsNull.notNullValue;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
LazyManyToOneEmbeddedIdWithToOneFKTest.System.class,
|
||||
LazyManyToOneEmbeddedIdWithToOneFKTest.SystemUser.class,
|
||||
LazyManyToOneEmbeddedIdWithToOneFKTest.Subsystem.class
|
||||
}
|
||||
)
|
||||
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
|
||||
public class LazyManyToOneEmbeddedIdWithToOneFKTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Subsystem subsystem = new Subsystem( 2, "sub1" );
|
||||
PK userKey = new PK( subsystem, "Fab" );
|
||||
SystemUser user = new SystemUser( userKey, "Fab" );
|
||||
|
||||
System system = new System( 1, "sub1" );
|
||||
system.setUser( user );
|
||||
|
||||
session.save( subsystem );
|
||||
session.save( user );
|
||||
session.save( system );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from System" ).executeUpdate();
|
||||
session.createQuery( "delete from SystemUser" ).executeUpdate();
|
||||
session.createQuery( "delete from Subsystem" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = session.get( System.class, 1 );
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
|
||||
assertThat( system.getId(), is( 1 ) );
|
||||
|
||||
assertFalse( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
PK pk = system.getUser().getPk();
|
||||
assertTrue( Hibernate.isInitialized( pk.subsystem ) );
|
||||
|
||||
assertThat( pk.username, is( "Fab" ) );
|
||||
assertThat( pk.subsystem.id, is( 2 ) );
|
||||
assertThat( pk.subsystem.getDescription(), is( "sub1" ) );
|
||||
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||
|
||||
statementInspector.clear();
|
||||
assertThat( user.getName(), is( "Fab" ) );
|
||||
assertTrue( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHql(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = (System) session.createQuery( "from System e where e.id = :id" )
|
||||
.setParameter( "id", 1 ).uniqueResult();
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||
|
||||
assertFalse( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
final PK pk = system.getUser().getPk();
|
||||
assertTrue( Hibernate.isInitialized( pk.subsystem ) );
|
||||
|
||||
assertThat( pk.username, is( "Fab" ) );
|
||||
assertThat( pk.subsystem.id, is( 2 ) );
|
||||
assertThat( pk.subsystem.getDescription(), is( "sub1" ) );
|
||||
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
|
||||
statementInspector.clear();
|
||||
assertThat( user.getName(), is( "Fab" ) );
|
||||
assertTrue( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlJoin(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = session.createQuery( "from System e join e.user where e.id = :id", System.class )
|
||||
.setParameter( "id", 1 ).uniqueResult();
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||
|
||||
assertFalse( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlJoinFetch(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = session.createQuery(
|
||||
"from System e join fetch e.user where e.id = :id",
|
||||
System.class
|
||||
)
|
||||
.setParameter( "id", 1 ).uniqueResult();
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||
|
||||
assertTrue( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "System")
|
||||
public static class System {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
SystemUser user;
|
||||
|
||||
public System() {
|
||||
}
|
||||
|
||||
public System(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public SystemUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(SystemUser user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "SystemUser")
|
||||
public static class SystemUser {
|
||||
|
||||
@EmbeddedId
|
||||
private PK pk;
|
||||
|
||||
private String name;
|
||||
|
||||
public SystemUser() {
|
||||
}
|
||||
|
||||
public SystemUser(PK pk, String name) {
|
||||
this.pk = pk;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public PK getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setPk(PK pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class PK implements Serializable {
|
||||
|
||||
@ManyToOne
|
||||
private Subsystem subsystem;
|
||||
|
||||
private String username;
|
||||
|
||||
public PK(Subsystem subsystem, String username) {
|
||||
this.subsystem = subsystem;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
private PK() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
PK pk = (PK) o;
|
||||
return Objects.equals( subsystem, pk.subsystem ) &&
|
||||
Objects.equals( username, pk.username );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( subsystem, username );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Subsystem")
|
||||
public static class Subsystem {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String description;
|
||||
|
||||
public Subsystem() {
|
||||
}
|
||||
|
||||
public Subsystem(Integer id, String description) {
|
||||
this.id = id;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
// public Integer getId() {
|
||||
// return id;
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* 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.compositefk;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsNull.notNullValue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
ManyToOneEmbeddedIdWithLazyToOneFKTest.System.class,
|
||||
ManyToOneEmbeddedIdWithLazyToOneFKTest.SystemUser.class,
|
||||
ManyToOneEmbeddedIdWithLazyToOneFKTest.Subsystem.class
|
||||
}
|
||||
)
|
||||
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
|
||||
public class ManyToOneEmbeddedIdWithLazyToOneFKTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Subsystem subsystem = new Subsystem( 2, "sub1" );
|
||||
PK userKey = new PK( subsystem, "Fab" );
|
||||
SystemUser user = new SystemUser( userKey, "Fab" );
|
||||
|
||||
System system = new System( 1, "sub1" );
|
||||
system.setUser( user );
|
||||
|
||||
session.save( subsystem );
|
||||
session.save( user );
|
||||
session.save( system );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete from System" ).executeUpdate();
|
||||
session.createQuery( "delete from SystemUser" ).executeUpdate();
|
||||
session.createQuery( "delete from Subsystem" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = session.get( System.class, 1 );
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
assertThat( system.getId(), is( 1 ) );
|
||||
|
||||
assertTrue( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
PK pk = system.getUser().getPk();
|
||||
assertFalse( Hibernate.isInitialized( pk.subsystem ) );
|
||||
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
||||
|
||||
statementInspector.clear();
|
||||
assertThat( pk.username, is( "Fab" ) );
|
||||
|
||||
Subsystem subsystem = pk.getSubsystem();
|
||||
assertThat( subsystem.getId(), is( 2 ) );
|
||||
assertThat( subsystem.getDescription(), is( "sub1" ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHql(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
/*
|
||||
select
|
||||
s1_0.id,
|
||||
s1_0.name,
|
||||
s1_0.user_subsystem_id,
|
||||
s1_0.user_username
|
||||
from
|
||||
System as s1_0
|
||||
where
|
||||
s1_0.id = ?
|
||||
|
||||
select
|
||||
s1_0.subsystem_id,
|
||||
s1_0.username,
|
||||
s1_0.name
|
||||
from
|
||||
SystemUser as s1_0
|
||||
where
|
||||
(
|
||||
s1_0.subsystem_id, s1_0.username
|
||||
) in (
|
||||
(
|
||||
?, ?
|
||||
)
|
||||
)
|
||||
*/
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = (System) session.createQuery( "from System e where e.id = :id" )
|
||||
.setParameter( "id", 1 ).uniqueResult();
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||
|
||||
assertTrue( Hibernate.isInitialized( system.getUser() ) );
|
||||
|
||||
final PK pk = system.getUser().getPk();
|
||||
assertFalse( Hibernate.isInitialized( pk.subsystem ) );
|
||||
|
||||
statementInspector.clear();
|
||||
assertThat( pk.username, is( "Fab" ) );
|
||||
|
||||
Subsystem subsystem = pk.getSubsystem();
|
||||
assertThat( subsystem.getId(), is( 2 ) );
|
||||
assertThat( subsystem.getDescription(), is( "sub1" ) );
|
||||
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlJoin(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = session.createQuery( "from System e join e.user where e.id = :id", System.class )
|
||||
.setParameter( "id", 1 ).uniqueResult();
|
||||
|
||||
statementInspector.assertExecutedCount( 2 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 0 );
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
|
||||
assertTrue( Hibernate.isInitialized( system.getUser() ) );
|
||||
assertFalse( Hibernate.isInitialized( system.getUser().getPk().subsystem ) );
|
||||
statementInspector.clear();
|
||||
PK pk = system.getUser().getPk();
|
||||
|
||||
assertThat( pk.username, is( "Fab" ) );
|
||||
|
||||
Subsystem subsystem = pk.getSubsystem();
|
||||
assertThat( subsystem.getId(), is( 2 ) );
|
||||
assertThat( subsystem.getDescription(), is( "sub1" ) );
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHqlJoinFetch(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
System system = session.createQuery(
|
||||
"from System e join fetch e.user where e.id = :id",
|
||||
System.class
|
||||
).setParameter( "id", 1 ).uniqueResult();
|
||||
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
|
||||
|
||||
assertThat( system, is( notNullValue() ) );
|
||||
SystemUser user = system.getUser();
|
||||
assertThat( user, is( notNullValue() ) );
|
||||
|
||||
statementInspector.clear();
|
||||
PK pk = system.getUser().getPk();
|
||||
|
||||
assertThat( pk.username, is( "Fab" ) );
|
||||
|
||||
Subsystem subsystem = pk.getSubsystem();
|
||||
assertThat( subsystem.getId(), is( 2 ) );
|
||||
assertThat( subsystem.getDescription(), is( "sub1" ) );
|
||||
statementInspector.assertExecutedCount( 1 );
|
||||
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "System")
|
||||
public static class System {
|
||||
@Id
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
@ManyToOne
|
||||
SystemUser user;
|
||||
|
||||
public System() {
|
||||
}
|
||||
|
||||
public System(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public SystemUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(SystemUser user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "SystemUser")
|
||||
public static class SystemUser {
|
||||
|
||||
@EmbeddedId
|
||||
private PK pk;
|
||||
|
||||
private String name;
|
||||
|
||||
public SystemUser() {
|
||||
}
|
||||
|
||||
public SystemUser(PK pk, String name) {
|
||||
this.pk = pk;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public PK getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
public void setPk(PK pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class PK implements Serializable {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private Subsystem subsystem;
|
||||
|
||||
private String username;
|
||||
|
||||
public PK(Subsystem subsystem, String username) {
|
||||
this.subsystem = subsystem;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
private PK() {
|
||||
}
|
||||
|
||||
public Subsystem getSubsystem() {
|
||||
return subsystem;
|
||||
}
|
||||
|
||||
public void setSubsystem(Subsystem subsystem) {
|
||||
this.subsystem = subsystem;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
PK pk = (PK) o;
|
||||
return Objects.equals( subsystem, pk.subsystem ) &&
|
||||
Objects.equals( username, pk.username );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( subsystem, username );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Subsystem")
|
||||
public static class Subsystem {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String description;
|
||||
|
||||
public Subsystem() {
|
||||
}
|
||||
|
||||
public Subsystem(Integer id, String description) {
|
||||
this.id = id;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -124,14 +124,18 @@ public class ManyToOneEmbeddedIdWithToOneFKTest {
|
|||
s2_0.id=?
|
||||
|
||||
select
|
||||
manytoonee0_.subsystem_id as subsyste3_2_0_,
|
||||
manytoonee0_.username as username1_2_0_,
|
||||
manytoonee0_.name as name2_2_0_
|
||||
s1_0.subsystem_id,
|
||||
s1_0.username
|
||||
from
|
||||
SystemUser manytoonee0_
|
||||
SystemUser as s1_0
|
||||
where
|
||||
manytoonee0_.subsystem_id=?
|
||||
and manytoonee0_.username=?
|
||||
(
|
||||
s1_0.subsystem_id, s1_0.username
|
||||
) in (
|
||||
(
|
||||
?, ?
|
||||
)
|
||||
)
|
||||
*/
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
|
|
Loading…
Reference in New Issue