Fix CollectionLoaderBatchKey parameters binding error

This commit is contained in:
Andrea Boriero 2021-05-25 16:16:17 +02:00 committed by Andrea Boriero
parent 629b318731
commit 21c607c929
21 changed files with 421 additions and 358 deletions

View File

@ -326,7 +326,7 @@ public class BatchFetchQueue {
}
if ( checkForEnd && i == end ) {
return keys; //the first key found after the given key
return resize( keys, i ); //the first key found after the given key
}
final boolean isEqual = collectionPersister.getKeyType().isEqual(
@ -352,7 +352,15 @@ public class BatchFetchQueue {
}
}
}
return keys; //we ran out of keys to try
return resize( keys, i ); //we ran out of keys to try
}
private Object[] resize(Object[] keys, int size) {
Object[] result = new Object[size];
for ( int i = 0; i < size; i++ ) {
result[i] = keys[i];
}
return result;
}
private boolean isCached(Object collectionKey, CollectionPersister persister) {

View File

@ -174,36 +174,37 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
jdbcParameters,
session
);
jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect,
jdbcParameterBindings,
new ExecutionContext() {
@Override
public SharedSessionContractImplementor getSession() {
return session;
}
@Override
public QueryOptions getQueryOptions() {
return QueryOptions.NONE;
}
@Override
public QueryParameterBindings getQueryParameterBindings() {
return QueryParameterBindings.NO_PARAM_BINDINGS;
}
@Override
public Callback getCallback() {
return null;
}
},
RowTransformerPassThruImpl.instance(),
true
);
}
jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect,
jdbcParameterBindings,
new ExecutionContext() {
@Override
public SharedSessionContractImplementor getSession() {
return session;
}
@Override
public QueryOptions getQueryOptions() {
return QueryOptions.NONE;
}
@Override
public QueryParameterBindings getQueryParameterBindings() {
return QueryParameterBindings.NO_PARAM_BINDINGS;
}
@Override
public Callback getCallback() {
return null;
}
},
RowTransformerPassThruImpl.instance(),
true
);
assert offset == jdbcParameters.size();
// prepare for the next round...

View File

@ -78,7 +78,6 @@ public class DeleteSharedOneToManyOrphansTest {
@Test
@TestForIssue(jiraKey = "HHH-11144")
@FailureExpected( jiraKey = "HHH-11144" )
public void testInitializingSecondCollection(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {

View File

@ -4,7 +4,7 @@
* 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.manytomany;
package org.hibernate.orm.test.manytomany;
import org.hibernate.annotations.Where;

View File

@ -4,7 +4,7 @@
* 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.manytomany;
package org.hibernate.orm.test.manytomany;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

View File

@ -6,7 +6,7 @@
*/
//$Id: Group.java 7085 2005-06-08 17:59:47Z oneovthafew $
package org.hibernate.test.manytomany;
package org.hibernate.orm.test.manytomany;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

View File

@ -4,11 +4,10 @@
* 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.manytomany;
package org.hibernate.orm.test.manytomany;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
@ -17,29 +16,37 @@ import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.hibernate.annotations.NaturalId;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.FailureExpected;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
/**
* @author Vlad Mihalcea
*/
public class ManyToManyBidirectionalTest extends BaseEntityManagerFunctionalTestCase {
@Jpa(
annotatedClasses = {
ManyToManyBidirectionalTest.Person.class,
ManyToManyBidirectionalTest.Address.class,
}
)
public class ManyToManyBidirectionalTest {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class,
Address.class,
};
@AfterEach
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
entityManager.createQuery( "delete from Person" ).executeUpdate();
entityManager.createQuery( "delete from Address" ).executeUpdate();
}
);
}
@Test
public void testRemoveOwnerSide() {
Person _person1 = doInJPA( this::entityManagerFactory, entityManager -> {
public void testRemoveOwnerSide(EntityManagerFactoryScope scope) {
Person _person1 = scope.fromTransaction( entityManager -> {
Person person1 = new Person( "ABC-123" );
Person person2 = new Person( "DEF-456" );
@ -57,7 +64,7 @@ public class ManyToManyBidirectionalTest extends BaseEntityManagerFunctionalTest
return person1;
} );
doInJPA( this::entityManagerFactory, entityManager -> {
scope.inTransaction( entityManager -> {
Person person1 = entityManager.find( Person.class, _person1.id );
entityManager.remove( person1 );
@ -65,9 +72,9 @@ public class ManyToManyBidirectionalTest extends BaseEntityManagerFunctionalTest
}
@Test
@FailureExpected( jiraKey = "HHH-12239")
public void testRemoveMappedBySide() {
Address _address1 = doInJPA( this::entityManagerFactory, entityManager -> {
@FailureExpected(jiraKey = "HHH-12239")
public void testRemoveMappedBySide(EntityManagerFactoryScope scope) {
Address _address1 = scope.fromTransaction( entityManager -> {
Person person1 = new Person( "ABC-123" );
Person person2 = new Person( "DEF-456" );
@ -85,7 +92,7 @@ public class ManyToManyBidirectionalTest extends BaseEntityManagerFunctionalTest
return address1;
} );
doInJPA( this::entityManagerFactory, entityManager -> {
scope.inTransaction( entityManager -> {
Address address1 = entityManager.find( Address.class, _address1.id );
entityManager.remove( address1 );
@ -102,7 +109,7 @@ public class ManyToManyBidirectionalTest extends BaseEntityManagerFunctionalTest
@NaturalId
private String registrationNumber;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private List<Address> addresses = new ArrayList<>();
public Person() {

View File

@ -4,66 +4,67 @@
* 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.manytomany;
package org.hibernate.orm.test.manytomany;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import org.hibernate.Hibernate;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
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.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
*/
public class ManyToManyTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "manytomany/UserGroup.hbm.xml" };
}
@Override
public void configure(Configuration cfg) {
cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "false");
}
@DomainModel(
xmlMappings = "org/hibernate/orm/test/manytomany/UserGroup.hbm.xml"
)
@SessionFactory
@ServiceRegistry(
settings = @Setting(name = Environment.USE_SECOND_LEVEL_CACHE, value = "false")
)
public class ManyToManyTest {
@Test
public void testManyToManyWithFormula() {
User user = new User("gavin", "jboss");
Group seamGroup = new Group("seam", "jboss");
Group hbGroup = new Group("hibernate", "jboss");
inTransaction(
public void testManyToManyWithFormula(SessionFactoryScope scope) {
User user = new User( "gavin", "jboss" );
Group seamGroup = new Group( "seam", "jboss" );
Group hbGroup = new Group( "hibernate", "jboss" );
scope.inTransaction(
s -> {
user.getGroups().add(seamGroup);
user.getGroups().add(hbGroup);
seamGroup.getUsers().add(user);
hbGroup.getUsers().add(user);
s.persist(user);
s.persist(seamGroup);
s.persist(hbGroup);
user.getGroups().add( seamGroup );
user.getGroups().add( hbGroup );
seamGroup.getUsers().add( user );
hbGroup.getUsers().add( user );
s.persist( user );
s.persist( seamGroup );
s.persist( hbGroup );
}
);
inTransaction(
scope.inTransaction(
s -> {
User gavin = s.get(User.class, user);
User gavin = s.get( User.class, user );
assertFalse( Hibernate.isInitialized( gavin.getGroups() ) );
assertEquals( 2, gavin.getGroups().size() );
Group hb = s.get(Group.class, hbGroup);
Group hb = s.get( Group.class, hbGroup );
assertFalse( Hibernate.isInitialized( hb.getUsers() ) );
assertEquals( 1, hb.getUsers().size() );
}
);
inTransaction(
scope.inTransaction(
s -> {
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<User> criteria = criteriaBuilder.createQuery( User.class );
@ -82,7 +83,7 @@ public class ManyToManyTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<User> criteria = criteriaBuilder.createQuery( User.class );
@ -102,9 +103,10 @@ public class ManyToManyTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
User gavin = (User) s.createQuery("from User u join fetch u.groups g join fetch g.users").uniqueResult();
User gavin = (User) s.createQuery( "from User u join fetch u.groups g join fetch g.users" )
.uniqueResult();
assertTrue( Hibernate.isInitialized( gavin.getGroups() ) );
assertEquals( 2, gavin.getGroups().size() );
Group group = (Group) gavin.getGroups().iterator().next();
@ -113,27 +115,28 @@ public class ManyToManyTest extends BaseCoreFunctionalTestCase {
}
);
inTransaction(
scope.inTransaction(
s -> {
User gavin = s.get(User.class, user);
Group hb = s.get(Group.class, hbGroup);
gavin.getGroups().remove(hb);
User gavin = s.get( User.class, user );
Group hb = s.get( Group.class, hbGroup );
gavin.getGroups().remove( hb );
}
);
inTransaction(
scope.inTransaction(
s -> {
User gavin = s.get(User.class, user);
assertEquals( gavin.getGroups().size(), 1 );
Group hb = s.get(Group.class, hbGroup);
assertEquals( hb.getUsers().size(), 0 );
User gavin = s.get( User.class, user );
assertEquals( 1, gavin.getGroups().size() );
Group hb = s.get( Group.class, hbGroup );
assertEquals( 0, hb.getUsers().size() );
}
);
inTransaction(
scope.inTransaction(
s -> {
s.delete(user);
s.delete( user );
s.flush();
s.createQuery("delete from Group").executeUpdate();
s.createQuery( "delete from Group" ).executeUpdate();
}
);
}

View File

@ -0,0 +1,96 @@
/*
* 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.manytomany;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import org.hibernate.testing.TestForIssue;
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.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Verifies that @ManyToMany relationships with a @Where clause properly
* loads the collection for issue HHH-9084.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-9084")
@DomainModel(
annotatedClasses = {
Advertisement.class,
Attachment.class,
PageAdvertisement.class,
SubjectAdvertisement.class
}
)
@SessionFactory
public class ManyToManyWhereTest {
@Test
public void testManyToManyWithWhereConditional(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
// create advertisements
Advertisement advertisement1 = new Advertisement();
Advertisement advertisement2 = new Advertisement();
session.saveOrUpdate( advertisement1 );
session.saveOrUpdate( advertisement2 );
// create attachment relationships to advertisements
Attachment a1 = new Attachment();
a1.setFileName( "memo.txt" );
a1.setAdvertisements( new LinkedHashSet<>( Arrays.asList( advertisement1, advertisement2 ) ) );
Attachment a2 = new Attachment();
a2.setFileName( "mickeymouse.jpg" );
a2.setDeleted( "true" );
a2.setAdvertisements( new LinkedHashSet<>( Arrays.asList( advertisement1, advertisement2 ) ) );
advertisement1.setAttachments( new HashSet<>( Arrays.asList( a1, a2 ) ) );
advertisement2.setAttachments( new HashSet<>( Arrays.asList( a1, a2 ) ) );
session.saveOrUpdate( a1 );
session.saveOrUpdate( a2 );
}
);
scope.inTransaction(
session -> {
// create page advertisement relationships with advertisements
List<Advertisement> advertisements = (List<Advertisement>) session.createQuery( "FROM Advertisement" )
.list();
assertEquals( 2, advertisements.size() );
for ( Advertisement advertisement : advertisements ) {
PageAdvertisement pageAd = new PageAdvertisement();
pageAd.setAdvertisement( advertisement );
session.persist( pageAd );
}
}
);
scope.inTransaction(
session -> {
// query relationships and verify @Where condition fragment applies correctly.
List<PageAdvertisement> ads = (List<PageAdvertisement>) session.createQuery(
"FROM PageAdvertisement" ).list();
assertEquals( 2, ads.size() );
for ( PageAdvertisement ad : ads ) {
// there is only 1 not deleted attachment
assertEquals( 1, ad.getAdvertisement().getAttachments().size() );
for ( Attachment attachment : ad.getAdvertisement().getAttachments() ) {
// each attachment linked with two advertisements
assertEquals( 2, attachment.getAdvertisements().size() );
}
}
}
);
}
}

View File

@ -4,7 +4,7 @@
* 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.manytomany;
package org.hibernate.orm.test.manytomany;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

View File

@ -4,7 +4,7 @@
* 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.manytomany;
package org.hibernate.orm.test.manytomany;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToOne;

View File

@ -6,7 +6,7 @@
*/
//$Id: User.java 7085 2005-06-08 17:59:47Z oneovthafew $
package org.hibernate.test.manytomany;
package org.hibernate.orm.test.manytomany;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

View File

@ -18,7 +18,7 @@
-->
<hibernate-mapping
package="org.hibernate.test.manytomany">
package="org.hibernate.orm.test.manytomany">
<class name="User" table="`User`">
<composite-id>

View File

@ -11,7 +11,7 @@
* 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.manytomany.mapkey;
package org.hibernate.orm.test.manytomany.mapkey;
import java.util.Collection;
import java.util.HashMap;
@ -25,14 +25,18 @@ import javax.persistence.MapKey;
import javax.persistence.Table;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
@ -41,22 +45,22 @@ import static org.junit.Assert.assertThat;
* @author Andrea Boriero
*/
@TestForIssue(jiraKey = "HHH-4235")
@RequiresDialectFeature(DialectChecks.SupportSchemaCreation.class)
public class ManyToManyWithMaykeyAndSchemaDefinitionTest extends BaseCoreFunctionalTestCase {
@RequiresDialectFeature(feature = DialectFeatureChecks.SupportSchemaCreation.class)
@DomainModel(
annotatedClasses = {
ManyToManyWithMaykeyAndSchemaDefinitionTest.EntityA.class,
ManyToManyWithMaykeyAndSchemaDefinitionTest.EntityB.class
}
)
@SessionFactory
@ServiceRegistry(
settings = @Setting(name = AvailableSettings.HBM2DDL_CREATE_SCHEMAS, value = "true")
)
public class ManyToManyWithMaykeyAndSchemaDefinitionTest {
@Override
protected void configure(Configuration configuration) {
configuration.setProperty( AvailableSettings.HBM2DDL_CREATE_SCHEMAS, "true" );
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { EntityA.class, EntityB.class };
}
@Before
public void setUp() {
inTransaction(
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityA entityA = new EntityA();
entityA.setId( 1L );
@ -70,10 +74,19 @@ public class ManyToManyWithMaykeyAndSchemaDefinitionTest extends BaseCoreFunctio
);
}
@Test
public void testRetrievingTheMapGeneratesACorrectlyQuery() {
@AfterEach
public void tearDown(SessionFactoryScope scope){
scope.inTransaction(
session -> {
session.createQuery( "delete from EntityA" ).executeUpdate();
session.createQuery( "delete from EntityB" ).executeUpdate();
}
);
}
inTransaction(
@Test
public void testRetrievingTheMapGeneratesACorrectlyQuery(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityA entityA = session.get( EntityA.class, 1L );
Collection<EntityB> values = entityA.getEntityBMap().values();

View File

@ -4,7 +4,7 @@
* 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.manytomany.ordered;
package org.hibernate.orm.test.manytomany.ordered;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

View File

@ -4,7 +4,7 @@
* 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.manytomany.ordered;
package org.hibernate.orm.test.manytomany.ordered;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
@ -12,38 +12,39 @@ import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import org.hibernate.Hibernate;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
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.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Gavin King
*/
public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "manytomany/ordered/UserGroup.hbm.xml" };
}
@Override
public void configure(Configuration cfg) {
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "false");
}
@DomainModel(
xmlMappings = "org/hibernate/orm/test/manytomany/ordered/UserGroup.hbm.xml"
)
@SessionFactory
@ServiceRegistry(
settings = @Setting(name = Environment.USE_SECOND_LEVEL_CACHE, value = "false")
)
public class OrderedManyToManyTest {
@Test
public void testManyToManyOrdering() {
public void testManyToManyOrdering(SessionFactoryScope scope) {
User gavin = new User( "gavin", "jboss" );
User steve = new User( "steve", "jboss" );
User max = new User( "max", "jboss" );
User emmanuel = new User( "emmanuel", "jboss" );
Group hibernate = new Group( "hibernate", "jboss" );
inTransaction(
scope.inTransaction(
s -> {
s.persist( gavin );
s.persist( steve );
@ -58,7 +59,7 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
);
// delayed collection load...
inTransaction(
scope.inTransaction(
s -> {
Group h = s.get( Group.class, hibernate.getId() );
assertFalse( Hibernate.isInitialized( h.getUsers() ) );
@ -68,7 +69,7 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
);
// HQL (non eager)
inTransaction(
scope.inTransaction(
s -> {
Group h = (Group) s.createQuery( "from Group" ).uniqueResult();
assertFalse( Hibernate.isInitialized( h.getUsers() ) );
@ -79,9 +80,9 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
// HQL (eager)
inTransaction(
scope.inTransaction(
s -> {
Group h = ( Group ) s.createQuery( "from Group g inner join fetch g.users" ).uniqueResult();
Group h = (Group) s.createQuery( "from Group g inner join fetch g.users" ).uniqueResult();
assertTrue( Hibernate.isInitialized( h.getUsers() ) );
assertEquals( 4, h.getUsers().size() );
assertOrdering( h.getUsers() );
@ -89,7 +90,7 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
);
// criteria load (forced eager fetch)
inTransaction(
scope.inTransaction(
s -> {
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<Group> criteria = criteriaBuilder.createQuery( Group.class );
@ -107,7 +108,7 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
// criteria load (forced non eager fetch)
inTransaction(
scope.inTransaction(
s -> {
CriteriaBuilder criteriaBuilder = s.getCriteriaBuilder();
CriteriaQuery<Group> criteria = criteriaBuilder.createQuery( Group.class );
@ -125,7 +126,7 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
// clean up
inTransaction(
scope.inTransaction(
s -> {
s.delete( gavin );
s.delete( steve );
@ -138,17 +139,17 @@ public class OrderedManyToManyTest extends BaseCoreFunctionalTestCase {
private void assertOrdering(List users) {
User user = extractUser( users, 0 );
assertTrue( "many-to-many ordering not applied", user.getName().equals( "emmanuel" ) );
assertTrue( user.getName().equals( "emmanuel" ), "many-to-many ordering not applied" );
user = extractUser( users, 1 );
assertTrue( "many-to-many ordering not applied", user.getName().equals( "gavin" ) );
assertTrue( user.getName().equals( "gavin" ), "many-to-many ordering not applied" );
user = extractUser( users, 2 );
assertTrue( "many-to-many ordering not applied", user.getName().equals( "max" ) );
assertTrue( user.getName().equals( "max" ), "many-to-many ordering not applied" );
user = extractUser( users, 3 );
assertTrue( "many-to-many ordering not applied", user.getName().equals( "steve" ) );
assertTrue( user.getName().equals( "steve" ), "many-to-many ordering not applied" );
}
private User extractUser(List users, int position) {
return ( User ) users.get( position );
return (User) users.get( position );
}
}

View File

@ -4,7 +4,7 @@
* 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.manytomany.ordered;
package org.hibernate.orm.test.manytomany.ordered;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

View File

@ -18,7 +18,7 @@
-->
<hibernate-mapping
package="org.hibernate.test.manytomany.ordered">
package="org.hibernate.orm.test.manytomany.ordered">
<class name="User" table="`User`">

View File

@ -1,93 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.manytomany;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* Verifies that @ManyToMany relationships with a @Where clause properly
* loads the collection for issue HHH-9084.
*
* @author Chris Cranford
*/
@TestForIssue( jiraKey = "HHH-9084" )
public class ManyToManyWhereTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Advertisement.class,
Attachment.class,
PageAdvertisement.class,
SubjectAdvertisement.class
};
}
@Test
public void testManyToManyWithWhereConditional() {
Session session = openSession();
Transaction transaction = session.beginTransaction();
// create advertisements
Advertisement advertisement1 = new Advertisement();
Advertisement advertisement2 = new Advertisement();
session.saveOrUpdate( advertisement1 );
session.saveOrUpdate( advertisement2 );
// create attachment relationships to advertisements
Attachment a1 = new Attachment();
a1.setFileName( "memo.txt" );
a1.setAdvertisements( new LinkedHashSet<>( Arrays.asList( advertisement1, advertisement2 ) ) );
Attachment a2 = new Attachment();
a2.setFileName( "mickeymouse.jpg" );
a2.setDeleted( "true" );
a2.setAdvertisements( new LinkedHashSet<>( Arrays.asList( advertisement1, advertisement2 ) ) );
advertisement1.setAttachments( new HashSet<>( Arrays.asList( a1, a2 ) ) );
advertisement2.setAttachments( new HashSet<>( Arrays.asList( a1, a2 ) ) );
session.saveOrUpdate( a1 );
session.saveOrUpdate( a2 );
transaction.commit();
session.close();
// create page advertisement relationships with advertisements
session = openSession();
transaction = session.beginTransaction();
List<Advertisement> advertisements = (List<Advertisement>) session.createQuery( "FROM Advertisement" ).list();
assertEquals( advertisements.size(), 2 );
for ( Advertisement advertisement : advertisements ) {
PageAdvertisement pageAd = new PageAdvertisement();
pageAd.setAdvertisement( advertisement );
session.persist( pageAd );
}
transaction.commit();
session.close();
// query relationships and verify @Where condition fragment applies correctly.
session = openSession();
transaction = session.beginTransaction();
List<PageAdvertisement> ads = (List<PageAdvertisement>) session.createQuery( "FROM PageAdvertisement" ).list();
assertEquals( ads.size(), 2 );
for ( PageAdvertisement ad : ads ) {
// there is only 1 not deleted attachment
assertEquals( ad.getAdvertisement().getAttachments().size(), 1 );
for( Attachment attachment : ad.getAdvertisement().getAttachments() ) {
// each attachment linked with two advertisements
assertEquals( attachment.getAdvertisements().size(), 2 );
}
}
transaction.commit();
session.close();
}
}

View File

@ -13,22 +13,23 @@ import org.hibernate.EmptyInterceptor;
import org.hibernate.Hibernate;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl;
import org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.stat.CollectionStatistics;
import org.junit.Test;
import junit.framework.Assert;
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.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Tests loading of many-to-many collection which should trigger
@ -36,74 +37,20 @@ import static org.junit.Assert.assertTrue;
*
* @author Steve Ebersole
*/
public class BatchedManyToManyTest extends BaseCoreFunctionalTestCase {
@Override
public String[] getMappings() {
return new String[] { "manytomany/batchload/UserGroupBatchLoad.hbm.xml" };
}
@Override
public void configure(Configuration cfg) {
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "false" );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
cfg.setProperty( Environment.BATCH_STRATEGY, TestingBatchBuilder.class.getName() );
}
public static class TestingBatchBuilder extends BatchBuilderImpl {
@Override
public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
return new TestingBatch( key, jdbcCoordinator );
@DomainModel(
xmlMappings = "org/hibernate/test/manytomany/batchload/UserGroupBatchLoad.hbm.xml"
)
@SessionFactory(generateStatistics = true)
@ServiceRegistry(
settings = {
@Setting(name = Environment.USE_SECOND_LEVEL_CACHE, value = "false"),
@Setting(name = Environment.BATCH_STRATEGY, value = "org.hibernate.test.manytomany.batchload.TestingBatchBuilder"),
}
}
)
public class BatchedManyToManyTest {
public static class TestingBatch extends NonBatchingBatch {
public TestingBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
super( key, jdbcCoordinator );
}
}
@Test
public void testLoadingNonInverseSide() {
prepareTestData();
sessionFactory().getStatistics().clear();
CollectionStatistics userGroupStats = sessionFactory().getStatistics()
.getCollectionStatistics( User.class.getName() + ".groups" );
CollectionStatistics groupUserStats = sessionFactory().getStatistics()
.getCollectionStatistics( Group.class.getName() + ".users" );
Interceptor testingInterceptor = new EmptyInterceptor() {
@Override
public String onPrepareStatement(String sql) {
// ugh, this is the best way I could come up with to assert this.
// unfortunately, this is highly dependent on the dialect and its
// outer join fragment. But at least this wil fail on the majority
// of dialects...
Assert.assertFalse(
"batch load of many-to-many should use inner join",
sql.toLowerCase(Locale.ROOT).contains( "left outer join" )
);
return super.onPrepareStatement( sql );
}
};
Session s = openSession( testingInterceptor );
s.beginTransaction();
List users = s.createQuery( "from User u" ).list();
User user = ( User ) users.get( 0 );
assertTrue( Hibernate.isInitialized( user ) );
assertTrue( Hibernate.isInitialized( user.getGroups() ) );
user = ( User ) users.get( 1 );
assertTrue( Hibernate.isInitialized( user ) );
assertTrue( Hibernate.isInitialized( user.getGroups() ) );
assertEquals( 1, userGroupStats.getFetchCount() ); // should have been just one fetch (the batch fetch)
assertEquals( 1, groupUserStats.getFetchCount() ); // should have been just one fetch (the batch fetch)
s.getTransaction().commit();
s.close();
}
protected void prepareTestData() {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
// set up the test data
User me = new User( "steve" );
User you = new User( "not steve" );
@ -116,31 +63,85 @@ public class BatchedManyToManyTest extends BaseCoreFunctionalTestCase {
translators.getUsers().add( you );
you.getGroups().add( contributors );
contributors.getUsers().add( you );
Session s = openSession();
s.beginTransaction();
s.save( me );
s.save( you );
s.getTransaction().commit();
s.close();
scope.inTransaction(
session -> {
session.save( me );
session.save( you );
}
);
}
protected void cleanupTestData() {
@AfterEach
public void tearDown(SessionFactoryScope scope) {
// clean up the test data
Session s = openSession();
s.beginTransaction();
// User is the non-inverse side...
List<User> users = s.createQuery( "from User" ).list();
for ( User user : users ) {
s.delete( user );
}
s.flush();
s.createQuery( "delete Group" ).executeUpdate();
s.getTransaction().commit();
s.close();
scope.inTransaction(
session -> {
// User is the non-inverse side...
List<User> users = session.createQuery( "from User" ).list();
for ( User user : users ) {
session.delete( user );
}
session.flush();
session.createQuery( "delete Group" ).executeUpdate();
}
);
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
@Test
public void testLoadingNonInverseSide(SessionFactoryScope scope) {
final SessionFactoryImplementor sessionFactory = scope.getSessionFactory();
sessionFactory.getStatistics().clear();
CollectionStatistics userGroupStats = sessionFactory.getStatistics()
.getCollectionStatistics( User.class.getName() + ".groups" );
CollectionStatistics groupUserStats = sessionFactory.getStatistics()
.getCollectionStatistics( Group.class.getName() + ".users" );
Interceptor testingInterceptor = new EmptyInterceptor() {
@Override
public String onPrepareStatement(String sql) {
// ugh, this is the best way I could come up with to assert this.
// unfortunately, this is highly dependent on the dialect and its
// outer join fragment. But at least this wil fail on the majority
// of dialects...
assertFalse(
sql.toLowerCase( Locale.ROOT ).contains( "left outer join" ),
"batch load of many-to-many should use inner join"
);
return super.onPrepareStatement( sql );
}
};
try (final Session session = scope.getSessionFactory()
.withOptions()
.interceptor( testingInterceptor )
.openSession()) {
session.getTransaction().begin();
try {
List users = session.createQuery( "from User u" ).list();
User user = (User) users.get( 0 );
assertTrue( Hibernate.isInitialized( user ) );
assertTrue( Hibernate.isInitialized( user.getGroups() ) );
user = (User) users.get( 1 );
assertTrue( Hibernate.isInitialized( user ) );
assertTrue( Hibernate.isInitialized( user.getGroups() ) );
assertEquals(
1,
userGroupStats.getFetchCount()
); // should have been just one fetch (the batch fetch)
assertEquals(
1,
groupUserStats.getFetchCount()
); // should have been just one fetch (the batch fetch)
session.getTransaction().commit();
}
finally {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
}
}
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.manytomany.batchload;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl;
import org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
public class TestingBatchBuilder extends BatchBuilderImpl {
@Override
public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
return new TestingBatch( key, jdbcCoordinator );
}
public static class TestingBatch extends NonBatchingBatch {
public TestingBatch(BatchKey key, JdbcCoordinator jdbcCoordinator) {
super( key, jdbcCoordinator );
}
}
}