DATAJPA-252 - Applying sort to manually defined queries considers joins.
If a manually defined query uses outer joins, prefixing the sort criteria handed to the execution of the method causes an additional join being added as the JPA considers path expressions to be inner joins always (see Sect. 4.4.4, JPA 2.0 spec). We now parse the outer join aliases potentially used in a manually defined JPQL query and do not prefix the query with the root entity's alias.
This commit is contained in:
@@ -921,6 +921,19 @@ public class UserRepositoryTests {
|
||||
assertThat(all.getContent().isEmpty(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-252
|
||||
*/
|
||||
@Test
|
||||
public void bindsSortingToOuterJoinCorrectly() {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
// Managers not set, make sure adding the sort does not rule out those Users
|
||||
Page<User> result = repository.findAllPaged(new PageRequest(0, 10, new Sort("manager.lastname")));
|
||||
assertThat(result.getContent(), hasSize((int) repository.count()));
|
||||
}
|
||||
|
||||
private Page<User> executeSpecWithSort(Sort sort) {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryUtils}.
|
||||
@@ -131,8 +134,52 @@ public class QueryUtilsUnitTests {
|
||||
assertCountQuery(FQ_QUERY, "select count(u) from org.acme.domain.User$Foo_Bar u");
|
||||
}
|
||||
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
/**
|
||||
* @see DATAJPA-252
|
||||
*/
|
||||
@Test
|
||||
public void detectsJoinAliasesCorrectly() {
|
||||
|
||||
Set<String> aliases = getOuterJoinAliases("select p from Person p left outer join x.foo b2_$ar where …");
|
||||
assertThat(aliases, hasSize(1));
|
||||
assertThat(aliases, hasItems("b2_$ar"));
|
||||
|
||||
aliases = getOuterJoinAliases("select p from Person p left join x.foo b2_$ar where …");
|
||||
assertThat(aliases, hasSize(1));
|
||||
assertThat(aliases, hasItems("b2_$ar"));
|
||||
|
||||
aliases = getOuterJoinAliases("select p from Person p left outer join x.foo as b2_$ar, left join x.bar as foo where …");
|
||||
assertThat(aliases, hasSize(2));
|
||||
assertThat(aliases, hasItems("b2_$ar", "foo"));
|
||||
|
||||
aliases = getOuterJoinAliases("select p from Person p left join x.foo as b2_$ar, left outer join x.bar foo where …");
|
||||
assertThat(aliases, hasSize(2));
|
||||
assertThat(aliases, hasItems("b2_$ar", "foo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-252
|
||||
*/
|
||||
@Test
|
||||
public void doesNotPrefixOrderReferenceIfOuterJoinAliasDetected() {
|
||||
|
||||
String query = "select p from Person p left join p.address address";
|
||||
assertThat(applySorting(query, new Sort("address.city")), endsWith("order by address.city asc"));
|
||||
assertThat(applySorting(query, new Sort("address.city", "lastname"), "p"),
|
||||
endsWith("order by address.city asc, p.lastname asc"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-252
|
||||
*/
|
||||
@Test
|
||||
public void extendsExistingOrderByClausesCorrectly() {
|
||||
|
||||
String query = "select p from Person p order by p.lastname asc";
|
||||
assertThat(applySorting(query, new Sort("firstname"), "p"), endsWith("order by p.lastname asc, p.firstname asc"));
|
||||
}
|
||||
|
||||
private void assertCountQuery(String originalQuery, String countQuery) {
|
||||
assertThat(createCountQueryFor(originalQuery), is(countQuery));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -68,7 +68,7 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
*/
|
||||
User findByEmailAddress(String emailAddress);
|
||||
|
||||
@Query("select u from User u ")
|
||||
@Query("select u from User u left outer join u.manager as manager")
|
||||
Page<User> findAllPaged(Pageable pageable);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user