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 ) { 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( 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) { private boolean isCached(Object collectionKey, CollectionPersister persister) {

View File

@ -174,6 +174,7 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
jdbcParameters, jdbcParameters,
session session
); );
}
jdbcServices.getJdbcSelectExecutor().list( jdbcServices.getJdbcSelectExecutor().list(
jdbcSelect, jdbcSelect,
@ -202,7 +203,7 @@ public class CollectionLoaderBatchKey implements CollectionLoader {
RowTransformerPassThruImpl.instance(), RowTransformerPassThruImpl.instance(),
true true
); );
}
assert offset == jdbcParameters.size(); assert offset == jdbcParameters.size();

View File

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

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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; import org.hibernate.annotations.Where;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;

View File

@ -6,7 +6,7 @@
*/ */
//$Id: Group.java 7085 2005-06-08 17:59:47Z oneovthafew $ //$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.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

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

View File

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

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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.MappedSuperclass;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;

View File

@ -6,7 +6,7 @@
*/ */
//$Id: User.java 7085 2005-06-08 17:59:47Z oneovthafew $ //$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.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

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

View File

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

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

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

View File

@ -18,7 +18,7 @@
--> -->
<hibernate-mapping <hibernate-mapping
package="org.hibernate.test.manytomany.ordered"> package="org.hibernate.orm.test.manytomany.ordered">
<class name="User" table="`User`"> <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.Hibernate;
import org.hibernate.Interceptor; import org.hibernate.Interceptor;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderImpl; import org.hibernate.engine.spi.SessionFactoryImplementor;
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.stat.CollectionStatistics; import org.hibernate.stat.CollectionStatistics;
import org.junit.Test; import org.hibernate.testing.orm.junit.DomainModel;
import junit.framework.Assert; 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 * Tests loading of many-to-many collection which should trigger
@ -36,74 +37,20 @@ import static org.junit.Assert.assertTrue;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BatchedManyToManyTest extends BaseCoreFunctionalTestCase { @DomainModel(
@Override xmlMappings = "org/hibernate/test/manytomany/batchload/UserGroupBatchLoad.hbm.xml"
public String[] getMappings() { )
return new String[] { "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 {
@Override @BeforeEach
public void configure(Configuration cfg) { public void setUp(SessionFactoryScope scope) {
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 );
}
}
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() {
// set up the test data // set up the test data
User me = new User( "steve" ); User me = new User( "steve" );
User you = new User( "not steve" ); User you = new User( "not steve" );
@ -116,31 +63,85 @@ public class BatchedManyToManyTest extends BaseCoreFunctionalTestCase {
translators.getUsers().add( you ); translators.getUsers().add( you );
you.getGroups().add( contributors ); you.getGroups().add( contributors );
contributors.getUsers().add( you ); contributors.getUsers().add( you );
Session s = openSession();
s.beginTransaction(); scope.inTransaction(
s.save( me ); session -> {
s.save( you ); session.save( me );
s.getTransaction().commit(); session.save( you );
s.close(); }
);
} }
protected void cleanupTestData() { @AfterEach
public void tearDown(SessionFactoryScope scope) {
// clean up the test data // clean up the test data
Session s = openSession(); scope.inTransaction(
s.beginTransaction(); session -> {
// User is the non-inverse side... // User is the non-inverse side...
List<User> users = s.createQuery( "from User" ).list(); List<User> users = session.createQuery( "from User" ).list();
for ( User user : users ) { for ( User user : users ) {
s.delete( user ); session.delete( user );
} }
s.flush(); session.flush();
s.createQuery( "delete Group" ).executeUpdate(); session.createQuery( "delete Group" ).executeUpdate();
s.getTransaction().commit(); }
s.close(); );
} }
@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 @Override
protected boolean isCleanupTestDataRequired() { public String onPrepareStatement(String sql) {
return true; // 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 );
}
}
}