From b73375c374372dce16f32d39a0e1c62672cdbcb0 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 9 Oct 2025 14:19:48 +0200 Subject: [PATCH] HHH-19851 Handle the calls to Session#findMultiple(EntityGraph...) for dynamic entities --- .../org/hibernate/internal/SessionImpl.java | 6 +- .../map/basic/DynamicClassTest.java | 165 ++++++++++-------- 2 files changed, 95 insertions(+), 76 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 38cf9f0cd77c..2fdbba2195a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -990,8 +990,12 @@ public List findMultiple(Class entityType, List ids, FindOption... @Override public List findMultiple(EntityGraph entityGraph, List ids, FindOption... options) { final RootGraph rootGraph = (RootGraph) entityGraph; + final ManagedDomainType type = rootGraph.getGraphedType(); final MultiIdentifierLoadAccess loadAccess = - byMultipleIds( rootGraph.getGraphedType().getJavaType() ); + switch ( type.getRepresentationMode() ) { + case MAP -> byMultipleIds( type.getTypeName() ); + case POJO -> byMultipleIds( type.getJavaType() ); + }; loadAccess.withLoadGraph( rootGraph ); setMultiIdentifierLoadAccessOptions( options, loadAccess ); return loadAccess.multiLoad( ids ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitymode/map/basic/DynamicClassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitymode/map/basic/DynamicClassTest.java index cdb379c619db..3020d8d6314f 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/entitymode/map/basic/DynamicClassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitymode/map/basic/DynamicClassTest.java @@ -4,95 +4,110 @@ */ package org.hibernate.orm.test.entitymode.map.basic; +import org.hibernate.Hibernate; +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 java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.hibernate.Hibernate; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; - -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +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.assertFalse; -import static org.junit.Assert.assertTrue; /** * @author Gavin King */ -public class DynamicClassTest extends BaseCoreFunctionalTestCase { - - @Override - protected String getBaseForMappings() { - return "org/hibernate/orm/test/"; - } - - @Override - public String[] getMappings() { - return new String[] { "entitymode/map/basic/ProductLine.hbm.xml" }; - } - - @Override - public void configure(Configuration cfg) { - } +@SessionFactory +@DomainModel( + xmlMappings = "org/hibernate/orm/test/entitymode/map/basic/ProductLine.hbm.xml" +) +class DynamicClassTest { @Test - public void testLazyDynamicClass() { - Session s = openSession(); - Transaction t = s.beginTransaction(); - - Map cars = new HashMap(); - cars.put("description", "Cars"); - Map monaro = new HashMap(); - monaro.put("productLine", cars); - monaro.put("name", "monaro"); - monaro.put("description", "Holden Monaro"); - Map hsv = new HashMap(); - hsv.put("productLine", cars); - hsv.put("name", "hsv"); - hsv.put("description", "Holden Commodore HSV"); - List models = new ArrayList(); - cars.put("models", models); - models.add(hsv); - models.add(monaro); - s.persist("ProductLine", cars); - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - - cars = (Map) s.createQuery("from ProductLine pl order by pl.description").uniqueResult(); - models = (List) cars.get("models"); - assertFalse( Hibernate.isInitialized(models) ); - assertEquals( models.size(), 2); - assertTrue( Hibernate.isInitialized(models) ); - - s.clear(); - - List list = s.createQuery("from Model m").list(); - for ( Iterator i=list.iterator(); i.hasNext(); ) { - assertFalse( Hibernate.isInitialized( ( (Map) i.next() ).get("productLine") ) ); - } - Map model = (Map) list.get(0); - assertTrue( ( (List) ( (Map) model.get("productLine") ).get("models") ).contains(model) ); - s.clear(); - - t.commit(); - s.close(); - - s = openSession(); - t = s.beginTransaction(); - cars = (Map) s.createQuery("from ProductLine pl order by pl.description").uniqueResult(); - s.remove(cars); - t.commit(); - s.close(); + void testLazyDynamicClass(SessionFactoryScope scope) { + scope.inTransaction( s -> { + Map cars = new HashMap<>(); + cars.put( "description", "Cars" ); + Map monaro = new HashMap<>(); + monaro.put( "productLine", cars ); + monaro.put( "name", "monaro" ); + monaro.put( "description", "Holden Monaro" ); + Map hsv = new HashMap<>(); + hsv.put( "productLine", cars ); + hsv.put( "name", "hsv" ); + hsv.put( "description", "Holden Commodore HSV" ); + List> models = new ArrayList<>(); + cars.put( "models", models ); + models.add( hsv ); + models.add( monaro ); + s.persist( "ProductLine", cars ); + } ); + + scope.inTransaction( s -> { + Map cars = (Map) s.createQuery( + "from ProductLine pl order by pl.description" ).uniqueResult(); + List> models = (List>) cars.get( "models" ); + assertFalse( Hibernate.isInitialized( models ) ); + assertEquals( 2, models.size() ); + assertTrue( Hibernate.isInitialized( models ) ); + + s.clear(); + + List list = s.createQuery( "from Model m" ).list(); + for ( Iterator i = list.iterator(); i.hasNext(); ) { + assertFalse( Hibernate.isInitialized( ((Map) i.next()).get( "productLine" ) ) ); + } + Map model = (Map) list.get( 0 ); + assertTrue( ((List>) ((Map) model.get( "productLine" )).get( + "models" )).contains( model ) ); + s.clear(); + + } ); + + scope.inTransaction( s -> { + Map cars = (Map) s.createQuery( + "from ProductLine pl order by pl.description" ).uniqueResult(); + s.remove( cars ); + } ); } + @Test + void multiload(SessionFactoryScope scope) { + final Object id = scope.fromTransaction( s -> { + Map cars = new HashMap<>(); + cars.put( "description", "Cars" ); + Map monaro = new HashMap<>(); + monaro.put( "productLine", cars ); + monaro.put( "name", "monaro" ); + monaro.put( "description", "Holden Monaro" ); + Map hsv = new HashMap<>(); + hsv.put( "productLine", cars ); + hsv.put( "name", "hsv" ); + hsv.put( "description", "Holden Commodore HSV" ); + List> models = new ArrayList<>(); + cars.put( "models", models ); + models.add( hsv ); + models.add( monaro ); + s.persist( "ProductLine", cars ); + + return cars.get( "id" ); + } ); + + scope.inTransaction( s -> { + var rootGraph = s.getSessionFactory().createGraphForDynamicEntity( "ProductLine" ); + + List> found = s.findMultiple( rootGraph, List.of( id ) ); + + assertThat( found ).hasSize( 1 ); + } ); + } }