HHH-7842 - Hibernate Criteria does not respect fetch mode, when alias is used
This commit is contained in:
parent
b48dfe0d11
commit
5be294506d
|
@ -166,6 +166,10 @@ public class CriteriaImpl implements Criteria, Serializable {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Criteria setFetchMode(String associationPath, FetchMode mode) {
|
public Criteria setFetchMode(String associationPath, FetchMode mode) {
|
||||||
|
String rootAliasPathPrefix = rootAlias + ".";
|
||||||
|
if (rootAlias != null && !associationPath.startsWith(rootAliasPathPrefix)) {
|
||||||
|
associationPath = rootAliasPathPrefix + associationPath;
|
||||||
|
}
|
||||||
fetchModes.put( associationPath, mode );
|
fetchModes.put( associationPath, mode );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,14 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
||||||
resolvedJoinType = JoinType.NONE;
|
resolvedJoinType = JoinType.NONE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FetchMode fetchMode = translator.getRootCriteria().getFetchMode( path.getFullPath() );
|
String fullPathWithAlias = path.getFullPath();
|
||||||
|
String rootAlias = translator.getRootCriteria().getAlias();
|
||||||
|
String rootAliasPathPrefix = rootAlias + ".";
|
||||||
|
if (rootAlias != null && !fullPathWithAlias.startsWith(rootAliasPathPrefix)) {
|
||||||
|
fullPathWithAlias = rootAliasPathPrefix + fullPathWithAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
FetchMode fetchMode = translator.getRootCriteria().getFetchMode( fullPathWithAlias );
|
||||||
if ( isDefaultFetchMode( fetchMode ) ) {
|
if ( isDefaultFetchMode( fetchMode ) ) {
|
||||||
if ( persister != null ) {
|
if ( persister != null ) {
|
||||||
if ( isJoinFetchEnabledByProfile( persister, path, propertyNumber ) ) {
|
if ( isJoinFetchEnabledByProfile( persister, path, propertyNumber ) ) {
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.criteria;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.Criteria;
|
||||||
|
import org.hibernate.FetchMode;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.criterion.CriteriaSpecification;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Thomas Reinhardt
|
||||||
|
*/
|
||||||
|
public class CriteriaAliasFetchTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyMetadataSources(MetadataSources metadataSources) {
|
||||||
|
super.applyMetadataSources( metadataSources );
|
||||||
|
metadataSources.addAnnotatedClass( Cat.class );
|
||||||
|
metadataSources.addAnnotatedClass( Kitten.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cleanupTest() throws Exception {
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
session.createQuery( "delete from " + Kitten.class.getName() ).executeUpdate();
|
||||||
|
session.createQuery( "delete from " + Cat.class.getName() ).executeUpdate();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void prepareTest() throws Exception {
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
|
||||||
|
// make 5 cats with 3 kittens each
|
||||||
|
for ( int i = 0; i < 5; i++ ) {
|
||||||
|
Cat cat = new Cat();
|
||||||
|
cat.catId = i;
|
||||||
|
cat.name = "cat_" + i;
|
||||||
|
session.save( cat );
|
||||||
|
for ( int j = 0; j < 3; j++ ) {
|
||||||
|
Kitten k = new Kitten();
|
||||||
|
k.kittenId = 5 * i + j;
|
||||||
|
k.name = "kitty_" + i + "_" + j;
|
||||||
|
k.cat = cat;
|
||||||
|
cat.kittens.add( k );
|
||||||
|
session.save( k );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertOnlyOneSelect(Criteria criteria) {
|
||||||
|
sessionFactory().getStatistics().setStatisticsEnabled( true );
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Cat> cats = criteria.list();
|
||||||
|
|
||||||
|
assertEquals( 5, cats.size() );
|
||||||
|
|
||||||
|
for ( Cat cat : cats ) {
|
||||||
|
assertEquals( 3, cat.kittens.size() );
|
||||||
|
|
||||||
|
for ( Kitten kitten : cat.kittens ) {
|
||||||
|
assertNotNull( kitten.cat );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals( "too many statements generated", 1, sessionFactory().getStatistics().getPrepareStatementCount() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
sessionFactory().getStatistics().setStatisticsEnabled( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-7842")
|
||||||
|
public void testFetchWithAlias() {
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
|
||||||
|
assertOnlyOneSelect( session.createCriteria( Cat.class, "c" )
|
||||||
|
.setFetchMode( "c.kittens", FetchMode.JOIN )
|
||||||
|
.setResultTransformer( CriteriaSpecification.DISTINCT_ROOT_ENTITY ) );
|
||||||
|
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFixForHHH7842DoesNotBreakOldBehavior() {
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
|
||||||
|
assertOnlyOneSelect( session.createCriteria( Cat.class )
|
||||||
|
.setFetchMode( "kittens", FetchMode.JOIN )
|
||||||
|
.setResultTransformer( CriteriaSpecification.DISTINCT_ROOT_ENTITY ) );
|
||||||
|
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Cat")
|
||||||
|
public static class Cat {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer catId;
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "cat")
|
||||||
|
public java.util.Set<Kitten> kittens = new java.util.HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Kitten")
|
||||||
|
public static class Kitten {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Integer kittenId;
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
public Cat cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue