diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/LoadManyRequest.java b/ebean-core/src/main/java/io/ebeaninternal/api/LoadManyRequest.java index 887d80b436..45470a9556 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/LoadManyRequest.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/LoadManyRequest.java @@ -93,19 +93,8 @@ private BeanPropertyAssocMany many() { public SpiQuery createQuery(SpiEbeanServer server) { BeanPropertyAssocMany many = many(); - SpiQuery query = many.newQuery(server); + SpiQuery query = many.newLoadManyQuery(server, onlyIds); query.usingTransaction(transaction); - String orderBy = many.lazyFetchOrderBy(); - if (orderBy != null) { - query.orderBy(orderBy); - } - String extraWhere = many.extraWhere(); - if (extraWhere != null) { - // replace special ${ta} placeholder with the base table alias - // which is always t0 and add the extra where clause - query.where().raw(extraWhere.replace("${ta}", "t0").replace("${mta}", "int_")); - } - query.setLazyLoadForParents(many); final var pc = loadContext.persistenceContext(); many.addWhereParentIdIn(query, parentIdList(server, many, pc), loadContext.isUseDocStore()); query.setPersistenceContext(pc); @@ -117,15 +106,7 @@ public SpiQuery createQuery(SpiEbeanServer server) { } // potentially changes the joins, selected properties, cache mode loadContext.configureQuery(query); - if (onlyIds) { - // lazy loading invoked via clear() and removeAll() - String mapKey = many.mapKey(); - if (mapKey != null) { - query.select(mapKey); - } else { - query.select(many.targetIdProperty()); - } - } + return query; } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultBeanLoader.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultBeanLoader.java index 2d8d005e2a..86b8a0f11e 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultBeanLoader.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultBeanLoader.java @@ -14,6 +14,7 @@ import io.ebeaninternal.server.transaction.DefaultPersistenceContext; import jakarta.persistence.EntityNotFoundException; + import java.util.List; import static java.lang.System.Logger.Level.DEBUG; @@ -77,7 +78,11 @@ private void loadManyInternal(EntityBean parentBean, String propertyName, boolea } } - SpiQuery query = server.createQuery(parentDesc.type()); + + SpiQuery query = many.newLoadManyQuery(server, onlyIds); + + many.addWhereParentIdIn(query, List.of(parentId), false); + if (refresh) { // populate a new collection BeanCollection emptyCollection = many.createEmpty(parentBean); @@ -87,26 +92,12 @@ private void loadManyInternal(EntityBean parentBean, String propertyName, boolea query.setLoadDescription("lazy", null); } - query.select(parentDesc.idBinder().idSelect()); - if (onlyIds) { - query.fetch(many.name(), many.targetIdProperty()); - } else { - query.fetch(many.name()); - } - if (filterMany != null) { - query.setFilterMany(many.name(), filterMany); - } - - query.where().idEq(parentId); - query.setBeanCacheMode(CacheMode.OFF); - query.setMode(Mode.LAZYLOAD_MANY); - query.setLazyLoadManyPath(many.name()); query.setPersistenceContext(pc); if (ebi.isReadOnly()) { query.setReadOnly(true); } - server.findOne(query); + server.findList(query); if (beanCollection != null) { if (beanCollection.checkEmptyLazyLoad()) { if (log.isLoggable(DEBUG)) { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java index cc40fed56f..efdc229483 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocMany.java @@ -1165,4 +1165,28 @@ public boolean createJoinTable() { return false; } } + + public SpiQuery newLoadManyQuery(SpiEbeanServer server, boolean onlyIds) { + SpiQuery query = newQuery(server); + String orderBy = lazyFetchOrderBy(); + if (orderBy != null) { + query.orderBy(orderBy); + } + String extraWhere = extraWhere(); + if (extraWhere != null) { + // replace special ${ta} placeholder with the base table alias + // which is always t0 and add the extra where clause + query.where().raw(extraWhere.replace("${ta}", "t0").replace("${mta}", "int_")); + } + query.setLazyLoadForParents(this); + if (onlyIds) { + // lazy loading invoked via clear() and removeAll() + if (mapKey() != null) { + query.select(mapKey()); + } else { + query.select(targetIdProperty()); + } + } + return query; + } } diff --git a/ebean-test/src/test/java/org/tests/cascade/TestOrderedList.java b/ebean-test/src/test/java/org/tests/cascade/TestOrderedList.java index 695d72548f..c42af2880b 100644 --- a/ebean-test/src/test/java/org/tests/cascade/TestOrderedList.java +++ b/ebean-test/src/test/java/org/tests/cascade/TestOrderedList.java @@ -19,7 +19,7 @@ public void test() { List details = master.getDetails(); for (int i = 0; i < 5; i++) { - details.add(new OmOrderedDetail("d"+i)); + details.add(new OmOrderedDetail("d" + i)); } LoggedSql.start(); @@ -188,4 +188,55 @@ public void testModifyListWithCache() { assertThat(masterDb.getDetails()).containsExactlyInAnyOrder(detail3, detail1); } + + @Test + public void testModifyListWithCache2() { + final OmCacheOrderedMaster master = new OmCacheOrderedMaster("Master"); + final OmCacheOrderedDetail detail1 = new OmCacheOrderedDetail("Detail1"); + // detail1.setId(2L); + final OmCacheOrderedDetail detail2 = new OmCacheOrderedDetail("Detail2"); + // detail2.setId(1L); + final OmCacheOrderedDetail detail3 = new OmCacheOrderedDetail("Detail3"); + // detail3.setId(3L); + DB.save(detail1); + DB.save(detail2); + DB.save(detail3); + master.getDetails().add(detail1); + master.getDetails().add(detail2); + master.getDetails().add(detail3); + + DB.save(master); + + OmCacheOrderedMaster masterDb = DB.find(OmCacheOrderedMaster.class, master.getId()); // load cache + assertThat(masterDb.getDetails()).containsExactly(detail1, detail2, detail3); + + masterDb = DB.find(OmCacheOrderedMaster.class, master.getId()); + assertThat(masterDb.getDetails()).containsExactly(detail1, detail2, detail3); // hit cache + + // 1 und 2 tauschen + masterDb.getDetails().add(0, masterDb.getDetails().remove(1)); + DB.save(masterDb); + + masterDb.getDetails().remove(2); + DB.save(masterDb); + + LoggedSql.start(); + OmCacheOrderedMaster masterDbNew = DB.find(OmCacheOrderedMaster.class, master.getId()); + masterDbNew.getDetails().size(); + assertThat(masterDbNew.getDetails()).containsExactly(detail2, detail1); + List sql = LoggedSql.stop(); + assertThat(sql).hasSize(1).first().asString() + .startsWith("select t0.master_id, t0.id, t0.name, t0.version, t0.sort_order, t0.master_id from om_cache_ordered_detail t0 where (t0.master_id) in (?) order by t0.master_id, t0.sort_order;"); + + DB.cacheManager().clearAll(); + masterDbNew = DB.find(OmCacheOrderedMaster.class, master.getId()); + LoggedSql.start(); + masterDbNew.getDetails().size(); + sql = LoggedSql.stop(); + assertThat(sql).hasSize(1).first().asString() + .startsWith("select t0.master_id, t0.id, t0.name, t0.version, t0.sort_order, t0.master_id from om_cache_ordered_detail t0 where (t0.master_id) in (?) order by t0.master_id, t0.sort_order;"); + + + assertThat(masterDbNew.getDetails()).containsExactly(detail2, detail1); + } }