Skip to content

Commit 17c3914

Browse files
committed
HHH-19142 StatelessSession.getMultiple() and second-level cache
1 parent 90780a0 commit 17c3914

File tree

3 files changed

+98
-9
lines changed

3 files changed

+98
-9
lines changed

hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java

+35-9
Original file line numberDiff line numberDiff line change
@@ -757,19 +757,45 @@ public <T> List<T> getMultiple(Class<T> entityClass, List<Object> ids) {
757757
throw new IllegalArgumentException("Null id");
758758
}
759759
}
760+
760761
final EntityPersister persister = requireEntityPersister( entityClass.getName() );
762+
763+
final List<Object> uncachedIds;
764+
final List<T> list = new ArrayList<>( ids.size() );
765+
if ( persister.canReadFromCache() ) {
766+
uncachedIds = new ArrayList<>( ids.size() );
767+
for (Object id : ids) {
768+
final Object cachedEntity =
769+
loadFromSecondLevelCache( this, null, LockMode.NONE, persister,
770+
generateEntityKey( id, persister ) );
771+
if ( cachedEntity == null ) {
772+
uncachedIds.add( id );
773+
list.add( null );
774+
}
775+
else {
776+
//noinspection unchecked
777+
list.add( (T) cachedEntity );
778+
}
779+
}
780+
}
781+
else {
782+
uncachedIds = ids;
783+
for (int i = 0; i < ids.size(); i++) {
784+
list.add( null );
785+
}
786+
}
787+
761788
final JpaCriteriaQuery<T> query = getCriteriaBuilder().createQuery(entityClass);
762789
final JpaRoot<T> from = query.from(entityClass);
763-
query.where( from.get( persister.getIdentifierPropertyName() ).in(ids) );
790+
query.where( from.get( persister.getIdentifierPropertyName() ).in(uncachedIds) );
764791
final List<T> resultList = createSelectionQuery(query).getResultList();
765-
final List<Object> idList = new ArrayList<>( resultList.size() );
766-
for (T entity : resultList) {
767-
idList.add( persister.getIdentifier(entity, this) );
768-
}
769-
final List<T> list = new ArrayList<>( ids.size() );
770-
for (Object id : ids) {
771-
final int pos = idList.indexOf(id);
772-
list.add( pos < 0 ? null : resultList.get(pos) );
792+
for (int i = 0; i < ids.size(); i++) {
793+
if ( list.get(i) == null ) {
794+
final Object id = ids.get(i);
795+
list.set( i, resultList.stream()
796+
.filter( entity -> entity != null && persister.getIdentifier( entity, this ).equals(id) )
797+
.findFirst().orElse( null ) );
798+
}
773799
}
774800
return list;
775801
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.stateless;
6+
7+
import jakarta.persistence.Cacheable;
8+
import jakarta.persistence.Entity;
9+
import jakarta.persistence.Id;
10+
import org.hibernate.testing.orm.junit.DomainModel;
11+
import org.hibernate.testing.orm.junit.SessionFactory;
12+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
13+
import org.junit.jupiter.api.Test;
14+
15+
import java.util.List;
16+
17+
import static org.junit.jupiter.api.Assertions.assertEquals;
18+
import static org.junit.jupiter.api.Assertions.assertNull;
19+
20+
@SessionFactory(generateStatistics = true)
21+
@DomainModel(annotatedClasses = GetMultipleFromCacheTest.Record.class)
22+
public class GetMultipleFromCacheTest {
23+
@Test void test(SessionFactoryScope scope) {
24+
scope.inStatelessTransaction(s-> {
25+
s.insert(new Record(123L,"hello earth"));
26+
s.insert(new Record(456L,"hello mars"));
27+
});
28+
scope.inStatelessTransaction(s-> {
29+
List<Record> all = s.getMultiple(Record.class, List.of(456L, 123L, 2L));
30+
assertEquals("hello mars",all.get(0).message);
31+
assertEquals("hello earth",all.get(1).message);
32+
assertNull(all.get(2));
33+
});
34+
scope.getSessionFactory().getStatistics().clear();
35+
scope.inStatelessTransaction(s-> {
36+
List<Record> all = s.getMultiple(Record.class, List.of(123L, 2L, 456L));
37+
assertEquals("hello earth",all.get(0).message);
38+
assertEquals("hello mars",all.get(2).message);
39+
assertNull(all.get(1));
40+
});
41+
assertEquals( 2,
42+
scope.getSessionFactory().getStatistics().getSecondLevelCacheHitCount() );
43+
}
44+
@Entity @Cacheable
45+
static class Record {
46+
@Id Long id;
47+
String message;
48+
49+
Record(Long id, String message) {
50+
this.id = id;
51+
this.message = message;
52+
}
53+
54+
Record() {
55+
}
56+
}
57+
}

hibernate-core/src/test/java/org/hibernate/orm/test/stateless/GetMultipleTest.java

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public class GetMultipleTest {
3030
assertEquals("hello earth",all.get(1).message);
3131
assertNull(all.get(2));
3232
});
33+
scope.inStatelessTransaction(s-> {
34+
List<Record> all = s.getMultiple(Record.class, List.of(123L, 2L, 456L));
35+
assertEquals("hello earth",all.get(0).message);
36+
assertEquals("hello mars",all.get(2).message);
37+
assertNull(all.get(1));
38+
});
3339
}
3440
@Entity
3541
static class Record {

0 commit comments

Comments
 (0)