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
This commit is contained in:
Mark Paluch
2023-04-12 11:32:20 +02:00
parent 884a589e22
commit 806e02b56b
3 changed files with 30 additions and 5 deletions

View File

@@ -314,18 +314,17 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
@Override
public Object convert(Object source) {
if (!(source instanceof Tuple)) {
if (!(source instanceof Tuple tuple)) {
return source;
}
Tuple tuple = (Tuple) source;
List<TupleElement<?>> elements = tuple.getElements();
if (elements.size() == 1) {
Object value = tuple.get(elements.get(0));
if (type.isInstance(value) || value == null) {
if (type.getDomainType().isInstance(value) || type.isInstance(value) || value == null) {
return value;
}
}

View File

@@ -39,6 +39,8 @@ import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.provider.PersistenceProvider;
import org.springframework.data.jpa.repository.sample.RoleRepository;
import org.springframework.data.jpa.repository.sample.UserRepository;
import org.springframework.data.jpa.repository.sample.UserRepository.IdOnly;
import org.springframework.data.jpa.repository.sample.UserRepository.RolesAndFirstname;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -276,11 +278,28 @@ public class UserRepositoryFinderTests {
.containsExactlyInAnyOrder(dave, oliver);
}
@Test // DATAJPA-974
@Test // DATAJPA-974, GH-2815
void executesQueryWithProjectionContainingReferenceToPluralAttribute() {
assertThat(userRepository.findRolesAndFirstnameBy()) //
List<RolesAndFirstname> rolesAndFirstnameBy = userRepository.findRolesAndFirstnameBy();
assertThat(rolesAndFirstnameBy)
.isNotNull();
for (RolesAndFirstname rolesAndFirstname : rolesAndFirstnameBy) {
assertThat(rolesAndFirstname.getFirstname()).isNotNull();
assertThat(rolesAndFirstname.getRoles()).isNotNull();
}
}
@Test // GH-2815
void executesQueryWithProjectionThroughStringQuery() {
List<IdOnly> ids = userRepository.findIdOnly();
assertThat(ids).isNotNull();
assertThat(ids).extracting(IdOnly::getId).doesNotContainNull();
}
@Test // DATAJPA-1023, DATACMNS-959

View File

@@ -551,6 +551,9 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
List<RolesAndFirstname> findRolesAndFirstnameBy();
@Query(value = "FROM User u")
List<IdOnly> findIdOnly();
// DATAJPA-1172
@Query("select u from User u where u.age = :age")
List<User> findByStringAge(@Param("age") String age);
@@ -721,4 +724,8 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
interface EmailOnly {
String getEmailAddress();
}
interface IdOnly {
int getId();
}
}