Skip to content

Commit 0c90ff3

Browse files
committed
Adopt to changed Hibernate behavior returning domain types using tuple queries.
We now allow using the domain type when it is returned from a tuple query. This allows projections if the return value is not a Map. Closes #2815
1 parent efd572a commit 0c90ff3

File tree

3 files changed

+30
-5
lines changed

3 files changed

+30
-5
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -314,18 +314,17 @@ public TupleConverter(ReturnedType type) {
314314
@Override
315315
public Object convert(Object source) {
316316

317-
if (!(source instanceof Tuple)) {
317+
if (!(source instanceof Tuple tuple)) {
318318
return source;
319319
}
320320

321-
Tuple tuple = (Tuple) source;
322321
List<TupleElement<?>> elements = tuple.getElements();
323322

324323
if (elements.size() == 1) {
325324

326325
Object value = tuple.get(elements.get(0));
327326

328-
if (type.isInstance(value) || value == null) {
327+
if (type.getDomainType().isInstance(value) || type.isInstance(value) || value == null) {
329328
return value;
330329
}
331330
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import org.springframework.data.jpa.provider.PersistenceProvider;
4141
import org.springframework.data.jpa.repository.sample.RoleRepository;
4242
import org.springframework.data.jpa.repository.sample.UserRepository;
43+
import org.springframework.data.jpa.repository.sample.UserRepository.IdOnly;
44+
import org.springframework.data.jpa.repository.sample.UserRepository.RolesAndFirstname;
4345
import org.springframework.data.repository.query.QueryLookupStrategy;
4446
import org.springframework.test.context.ContextConfiguration;
4547
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -281,11 +283,28 @@ void translatesNotContainsToNotMemberOf() {
281283
.containsExactlyInAnyOrder(dave, oliver);
282284
}
283285

284-
@Test // DATAJPA-974
286+
@Test // DATAJPA-974, GH-2815
285287
void executesQueryWithProjectionContainingReferenceToPluralAttribute() {
286288

287-
assertThat(userRepository.findRolesAndFirstnameBy()) //
289+
List<RolesAndFirstname> rolesAndFirstnameBy = userRepository.findRolesAndFirstnameBy();
290+
291+
assertThat(rolesAndFirstnameBy)
288292
.isNotNull();
293+
294+
for (RolesAndFirstname rolesAndFirstname : rolesAndFirstnameBy) {
295+
assertThat(rolesAndFirstname.getFirstname()).isNotNull();
296+
assertThat(rolesAndFirstname.getRoles()).isNotNull();
297+
}
298+
}
299+
300+
@Test // GH-2815
301+
void executesQueryWithProjectionThroughStringQuery() {
302+
303+
List<IdOnly> ids = userRepository.findIdOnly();
304+
305+
assertThat(ids).isNotNull();
306+
307+
assertThat(ids).extracting(IdOnly::getId).doesNotContainNull();
289308
}
290309

291310
@Test // DATAJPA-1023, DATACMNS-959

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java

+7
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,9 @@ List<User> findUsersByFirstnameForSpELExpressionWithParameterIndexOnlyWithEntity
556556

557557
List<RolesAndFirstname> findRolesAndFirstnameBy();
558558

559+
@Query(value = "FROM User u")
560+
List<IdOnly> findIdOnly();
561+
559562
// DATAJPA-1172
560563
@Query("select u from User u where u.age = :age")
561564
List<User> findByStringAge(@Param("age") String age);
@@ -732,4 +735,8 @@ interface NameOnly {
732735
interface EmailOnly {
733736
String getEmailAddress();
734737
}
738+
739+
interface IdOnly {
740+
int getId();
741+
}
735742
}

0 commit comments

Comments
 (0)