diff --git a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java
index 6e51a13fe008..c52511c0aa01 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/jaxb/mapping/spi/JaxbPluralAttribute.java
@@ -26,6 +26,8 @@ public interface JaxbPluralAttribute extends JaxbPersistentAttribute, JaxbLockab
JaxbCollectionIdImpl getCollectionId();
void setCollectionId(JaxbCollectionIdImpl id);
+ Integer getBatchSize();
+ void setBatchSize(Integer size);
LimitedCollectionClassification getClassification();
void setClassification(LimitedCollectionClassification value);
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java
index e4746da126ef..b77deb2305a8 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/models/xml/internal/attr/CommonPluralAttributeProcessing.java
@@ -11,6 +11,7 @@
import org.hibernate.boot.jaxb.mapping.spi.JaxbPluralFetchModeImpl;
import org.hibernate.boot.models.HibernateAnnotations;
import org.hibernate.boot.models.JpaAnnotations;
+import org.hibernate.boot.models.annotations.internal.BatchSizeAnnotation;
import org.hibernate.boot.models.annotations.internal.FetchAnnotation;
import org.hibernate.boot.models.annotations.internal.MapKeyClassJpaAnnotation;
import org.hibernate.boot.models.annotations.internal.MapKeyColumnJpaAnnotation;
@@ -62,6 +63,14 @@ public static void applyPluralAttributeStructure(
}
}
+ if ( jaxbPluralAttribute.getBatchSize() != null ) {
+ final BatchSizeAnnotation batchSizeAnnotation = (BatchSizeAnnotation) memberDetails.applyAnnotationUsage(
+ HibernateAnnotations.BATCH_SIZE,
+ buildingContext
+ );
+ batchSizeAnnotation.size( jaxbPluralAttribute.getBatchSize() );
+ }
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// collection-structure
diff --git a/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd
index 1118b61457f8..dd5129f41c72 100644
--- a/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd
+++ b/hibernate-core/src/main/resources/org/hibernate/xsd/mapping/mapping-7.0.xsd
@@ -3313,6 +3313,9 @@
+
+
+
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/BatchFetchTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/BatchFetchTest.java
index 8b33fa53c275..026c6a47e57c 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/BatchFetchTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/BatchFetchTest.java
@@ -4,13 +4,7 @@
*/
package org.hibernate.orm.test.batchfetch;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
import org.hibernate.Hibernate;
-import org.hibernate.cfg.AvailableSettings;
-
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -19,6 +13,12 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hibernate.cfg.CacheSettings.USE_SECOND_LEVEL_CACHE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -27,166 +27,118 @@
/**
* @author Gavin King
*/
+@SuppressWarnings("JUnitMalformedDeclaration")
@DomainModel(
- xmlMappings = "org/hibernate/orm/test/batchfetch/ProductLine.hbm.xml",
+ xmlMappings = "org/hibernate/orm/test/batchfetch/ProductLine.xml",
annotatedClasses = BatchLoadableEntity.class
)
-@SessionFactory(
- generateStatistics = true
-)
-@ServiceRegistry(
- settings = {
- @Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "false")
- }
-)
+@SessionFactory(generateStatistics = true)
+@ServiceRegistry(settings = @Setting(name = USE_SECOND_LEVEL_CACHE, value = "false"))
public class BatchFetchTest {
@SuppressWarnings("unchecked")
@Test
public void testBatchFetch(SessionFactoryScope scope) {
- ProductLine ossProductLine = new ProductLine();
- Model hibernateModel = new Model( ossProductLine );
- scope.inTransaction(
- session -> {
- ProductLine cars = new ProductLine();
- cars.setDescription( "Cars" );
- Model monaro = new Model( cars );
- monaro.setName( "monaro" );
- monaro.setDescription( "Holden Monaro" );
- Model hsv = new Model( cars );
- hsv.setName( "hsv" );
- hsv.setDescription( "Holden Commodore HSV" );
- session.persist( cars );
-
- ossProductLine.setDescription( "OSS" );
- Model jboss = new Model( ossProductLine );
- jboss.setName( "JBoss" );
- jboss.setDescription( "JBoss Application Server" );
-
- hibernateModel.setName( "Hibernate" );
- hibernateModel.setDescription( "Hibernate" );
- Model cache = new Model( ossProductLine );
- cache.setName( "JBossCache" );
- cache.setDescription( "JBoss TreeCache" );
- session.persist( ossProductLine );
- }
- );
-
- scope.getSessionFactory().getCache().evictEntityData( Model.class );
- scope.getSessionFactory().getCache().evictEntityData( ProductLine.class );
-
- scope.inTransaction(
- session -> {
- List list = session.createQuery( "from ProductLine pl order by pl.description" )
- .list();
- ProductLine cars = list.get( 0 );
- ProductLine oss = list.get( 1 );
- assertFalse( Hibernate.isInitialized( cars.getModels() ) );
- assertFalse( Hibernate.isInitialized( oss.getModels() ) );
- assertEquals( 2, cars.getModels().size() ); //fetch both collections
- assertTrue( Hibernate.isInitialized( cars.getModels() ) );
- assertTrue( Hibernate.isInitialized( oss.getModels() ) );
-
- session.clear();
-
- List models = session.createQuery( "from Model m" ).list();
- Model hibernate = session.get( Model.class, hibernateModel.getId() );
- hibernate.getProductLine().getId();
- for ( Model aList : models ) {
- assertFalse( Hibernate.isInitialized( aList.getProductLine() ) );
- }
- assertEquals( hibernate.getProductLine().getDescription(), "OSS" ); //fetch both productlines
-
- session.clear();
-
- Iterator iter = session.createQuery( "from Model" ).list().iterator();
- models = new ArrayList();
- while ( iter.hasNext() ) {
- models.add( iter.next() );
- }
- Model m = models.get( 0 );
- m.getDescription(); //fetch a batch of 4
-
- session.clear();
-
- list = session.createQuery( "from ProductLine" ).list();
- ProductLine pl = list.get( 0 );
- ProductLine pl2 = list.get( 1 );
- session.evict( pl2 );
- pl.getModels().size(); //fetch just one collection! (how can we write an assertion for that??)
- }
- );
-
- scope.inTransaction(
- session -> {
- List list = session.createQuery( "from ProductLine pl order by pl.description" )
- .list();
- ProductLine cars = list.get( 0 );
- ProductLine oss = list.get( 1 );
- assertEquals( cars.getModels().size(), 2 );
- assertEquals( oss.getModels().size(), 3 );
- session.remove( cars );
- session.remove( oss );
- }
- );
+ ProductLine ossProductLine = new ProductLine( "OSS" );
+ Model hibernateModel = new Model( "Hibernate", "Hibernate", ossProductLine );
+ scope.inTransaction( (session) -> {
+ ProductLine cars = new ProductLine( "Cars" );
+ new Model( "monaro", "Holden Monaro", cars );
+ new Model( "hsv", "Holden Commodore HSV", cars );
+ session.persist( cars );
+
+ ossProductLine.setDescription( "OSS" );
+ new Model( "JBoss", "JBoss Application Server", ossProductLine );
+ new Model( "JBossCache", "JBoss TreeCache", ossProductLine );
+ session.persist( ossProductLine );
+ } );
+
+ scope.inTransaction( (session) -> {
+ List list = session.createQuery( "from ProductLine pl order by pl.description" ).list();
+ ProductLine cars = list.get( 0 );
+ ProductLine oss = list.get( 1 );
+ assertFalse( Hibernate.isInitialized( cars.getModels() ) );
+ assertFalse( Hibernate.isInitialized( oss.getModels() ) );
+ assertEquals( 2, cars.getModels().size() ); //fetch both collections
+ assertTrue( Hibernate.isInitialized( cars.getModels() ) );
+ assertTrue( Hibernate.isInitialized( oss.getModels() ) );
+ } );
+
+ scope.inTransaction( (session) -> {
+ List models = session.createQuery( "from Model m" ).list();
+ Model hibernate = session.find( Model.class, hibernateModel.getId() );
+ hibernate.getProductLine().getId();
+ for ( Model aList : models ) {
+ assertFalse( Hibernate.isInitialized( aList.getProductLine() ) );
+ }
+ //fetch both product lines
+ assertThat( hibernate.getProductLine().getDescription() ).isEqualTo( "OSS" );
+ } );
+
+ scope.inTransaction( (session) -> {
+ Iterator iter = session.createQuery( "from Model" ).list().iterator();
+ ArrayList models = new ArrayList<>();
+ while ( iter.hasNext() ) {
+ models.add( iter.next() );
+ }
+ Model m = models.get( 0 );
+ m.getDescription(); //fetch a batch of 4
+
+ session.clear();
+
+ List list = session.createQuery( "from ProductLine" ).list();
+ ProductLine pl = list.get( 0 );
+ ProductLine pl2 = list.get( 1 );
+ session.evict( pl2 );
+ pl.getModels().size(); //fetch just one collection! (how can we write an assertion for that??)
+ } );
+
+ scope.inTransaction( (session) -> {
+ List list = session.createQuery( "from ProductLine pl order by pl.description" ).list();
+ ProductLine cars = list.get( 0 );
+ ProductLine oss = list.get( 1 );
+ assertThat( cars.getModels().size() ).isEqualTo( 2 );
+ assertThat( oss.getModels().size() ).isEqualTo( 3 );
+ } );
}
@Test
- @SuppressWarnings("unchecked")
public void testBatchFetch2(SessionFactoryScope scope) {
int size = 32 + 14;
- scope.inTransaction(
- session -> {
- for ( int i = 0; i < size; i++ ) {
- session.persist( new BatchLoadableEntity( i ) );
- }
- }
- );
-
- scope.inTransaction(
- session -> {
- // load them all as proxies
- for ( int i = 0; i < size; i++ ) {
- BatchLoadableEntity entity = session.getReference( BatchLoadableEntity.class, i );
- assertFalse( Hibernate.isInitialized( entity ) );
- }
- scope.getSessionFactory().getStatistics().clear();
- // now start initializing them...
- for ( int i = 0; i < size; i++ ) {
- BatchLoadableEntity entity = session.getReference( BatchLoadableEntity.class, i );
- Hibernate.initialize( entity );
- assertTrue( Hibernate.isInitialized( entity ) );
- }
- // so at this point, all entities are initialized. see how many fetches were performed.
- final int expectedFetchCount;
-// if ( sessionFactory().getSettings().getBatchFetchStyle() == BatchFetchStyle.LEGACY ) {
-// expectedFetchCount = 3; // (32 + 10 + 4)
-// }
-// else if ( sessionFactory().getSettings().getBatchFetchStyle() == BatchFetchStyle.DYNAMIC ) {
-// expectedFetchCount = 2; // (32 + 14) : because we limited batch-size to 32
-// }
-// else {
- // PADDED
- expectedFetchCount = 2; // (32 + 16*) with the 16 being padded
-// }
- assertEquals(
- expectedFetchCount,
- scope.getSessionFactory().getStatistics()
- .getEntityStatistics( BatchLoadableEntity.class.getName() )
- .getFetchCount()
- );
- }
- );
+ scope.inTransaction( (session) -> {
+ for ( int i = 0; i < size; i++ ) {
+ session.persist( new BatchLoadableEntity( i ) );
+ }
+ } );
+
+ scope.inTransaction( (session) -> {
+ // load them all as proxies
+ for ( int i = 0; i < size; i++ ) {
+ BatchLoadableEntity entity = session.getReference( BatchLoadableEntity.class, i );
+ assertFalse( Hibernate.isInitialized( entity ) );
+ }
+ scope.getSessionFactory().getStatistics().clear();
+ // now start initializing them...
+ for ( int i = 0; i < size; i++ ) {
+ BatchLoadableEntity entity = session.getReference( BatchLoadableEntity.class, i );
+ Hibernate.initialize( entity );
+ assertTrue( Hibernate.isInitialized( entity ) );
+ }
+ // so at this point, all entities are initialized. see how many fetches were performed.
+ final int expectedFetchCount;
+ expectedFetchCount = 2; // (32 + 16*) with the 16 being padded
+
+ assertEquals(
+ expectedFetchCount,
+ scope.getSessionFactory().getStatistics()
+ .getEntityStatistics( BatchLoadableEntity.class.getName() )
+ .getFetchCount()
+ );
+ } );
}
@AfterEach
public void tearDown(SessionFactoryScope scope) {
- scope.inTransaction(
- session -> {
- session.createQuery( "delete BatchLoadableEntity" ).executeUpdate();
- session.createQuery( "delete Model" ).executeUpdate();
- session.createQuery( "delete ProductLine" ).executeUpdate();
- }
- );
+ scope.dropData();
}
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/Model.java b/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/Model.java
index 72aecb38375c..3df626cf2127 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/Model.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/Model.java
@@ -9,16 +9,19 @@
* @author Gavin King
*/
public class Model {
- private String id;
+ private Integer id;
private String name;
private String description;
private ProductLine productLine;
- Model() {}
+ Model() {
+ }
- public Model(ProductLine pl) {
- this.productLine = pl;
- pl.getModels().add(this);
+ public Model(String name, String description, ProductLine productLine) {
+ this.name = name;
+ this.description = description;
+ this.productLine = productLine;
+ productLine.getModels().add(this);
}
public String getDescription() {
@@ -27,10 +30,10 @@ public String getDescription() {
public void setDescription(String description) {
this.description = description;
}
- public String getId() {
+ public Integer getId() {
return id;
}
- public void setId(String id) {
+ public void setId(Integer id) {
this.id = id;
}
public String getName() {
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/ProductLine.java b/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/ProductLine.java
index 81bc70b78681..fd44ea86fabb 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/ProductLine.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/batchfetch/ProductLine.java
@@ -10,21 +10,27 @@
* @author Gavin King
*/
public class ProductLine {
-
- private String id;
+ private Integer id;
private String description;
private Set models = new HashSet();
+ public ProductLine() {
+ }
+
+ public ProductLine(String description) {
+ this.description = description;
+ }
+
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
- public String getId() {
+ public Integer getId() {
return id;
}
- public void setId(String id) {
+ public void setId(Integer id) {
this.id = id;
}
public Set getModels() {
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/hql/ASTParserLoadingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/hql/ASTParserLoadingTest.java
index 2ad603699601..1bf0e275db38 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/hql/ASTParserLoadingTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/hql/ASTParserLoadingTest.java
@@ -105,7 +105,7 @@
"/org/hibernate/orm/test/hql/ComponentContainer.hbm.xml",
"/org/hibernate/orm/test/hql/VariousKeywordPropertyEntity.hbm.xml",
"/org/hibernate/orm/test/hql/Constructor.hbm.xml",
- "/org/hibernate/orm/test/batchfetch/ProductLine.hbm.xml",
+ "/org/hibernate/orm/test/batchfetch/ProductLine.xml",
"/org/hibernate/orm/test/cid/Customer.hbm.xml",
"/org/hibernate/orm/test/cid/Order.hbm.xml",
"/org/hibernate/orm/test/cid/LineItem.hbm.xml",
diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/batchfetch/ProductLine.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/orm/test/batchfetch/ProductLine.hbm.xml
deleted file mode 100644
index 2653901a0264..000000000000
--- a/hibernate-core/src/test/resources/org/hibernate/orm/test/batchfetch/ProductLine.hbm.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/batchfetch/ProductLine.xml b/hibernate-core/src/test/resources/org/hibernate/orm/test/batchfetch/ProductLine.xml
new file mode 100644
index 000000000000..0dfe2ff1ceaa
--- /dev/null
+++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/batchfetch/ProductLine.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+ org.hibernate.orm.test.batchfetch
+
+
+ 64
+
+
+
+
+
+
+
+
+ 64
+
+
+
+
+
+
+
+
+ 64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+