我正在尝试将Spring-Data-JPA合并到我的项目中。 有一件事让我感到困惑的是如何通过注释实现setMaxResults(n)?
例如,我的代码:
public interface UserRepository extends CrudRepository<User , Long>
{
@Query(value="From User u where u.otherObj = ?1 ")
public User findByOhterObj(OtherObj otherObj);
}
我只需要从otherObj返回one (and only one)
用户,但我找不到一种方法来注释maxResults ...有人可以给我一个提示吗?
(mysql抱怨:
com.mysql.jdbc.JDBC4PreparedStatement@5add5415: select user0_.id as id100_, user0_.created as created100_ from User user0_ where user0_.id=2 limit ** NOT SPECIFIED **
WARN util.JDBCExceptionReporter - SQL Error: 0, SQLState: 07001
ERROR util.JDBCExceptionReporter - No value specified for parameter 2
)
我找到了一个链接:https://jira.springsource.org/browse/DATAJPA-147, 我试过但失败了。现在似乎不可能? 为什么这么重要的功能没有内置在Spring-Data中?
如果我手动实现此功能:
public class UserRepositoryImpl implements UserRepository
我必须在CrudRepository
中实施大量的预定义方法,这将是非常糟糕的。
环境:spring-3.1,spring-data-jpa-1.0.3.RELEASE.jar,spring-data-commons-core-1.1.0.RELEASE.jar
答案 0 :(得分:161)
...您可以使用新引入的Top
和First
关键字来定义这样的查询方法:
findTop10ByLastnameOrderByFirstnameAsc(String lastname);
Spring Data会自动将结果限制为您定义的数字(如果省略则默认为1)。注意,结果的排序在这里变得相关(通过示例中看到的OrderBy
子句或通过将Sort
参数传递给方法)。请阅读涵盖new features of the Spring Data Evans release train或documentation。
要仅检索数据片段,Spring Data使用分页抽象,它在请求方提供Pageable
接口,在结果方面提供Page
抽象。所以你可以从
public interface UserRepository extends Repository<User, Long> {
List<User> findByUsername(String username, Pageable pageable);
}
并像这样使用它:
Pageable topTen = new PageRequest(0, 10);
List<User> result = repository.findByUsername("Matthews", topTen);
如果你需要知道结果的上下文(实际上是哪一页?它是第一个?总共有多少?)使用Page
作为返回类型:
public interface UserRepository extends Repository<User, Long> {
Page<User> findByUsername(String username, Pageable pageable);
}
客户端代码可以执行以下操作:
Pageable topTen = new PageRequest(0, 10);
Page<User> result = repository.findByUsername("Matthews", topTen);
Assert.assertThat(result.isFirstPage(), is(true));
如果您使用Page
作为返回类型,我们不会触发要执行的实际查询的计数投影,因为我们需要找出总计有多少元素来计算元数据。除此之外,请确保您实际上为PageRequest
配备了排序信息以获得稳定的结果。否则,您可能会触发查询两次并获得不同的结果,即使数据未在下面更改。
答案 1 :(得分:86)
如果您使用的是Java 8和Spring Data 1.7.0,如果要将@Query
注释与设置最大结果相结合,则可以使用默认方法:
public interface UserRepository extends PagingAndSortingRepository<User,Long> {
@Query("from User u where ...")
List<User> findAllUsersWhereFoo(@Param("foo") Foo foo, Pageable pageable);
default List<User> findTop10UsersWhereFoo(Foo foo) {
return findAllUsersWhereFoo(foo, new PageRequest(0,10));
}
}
答案 2 :(得分:26)
有一种方法可以提供“a by注释的setMaxResults(n)”,如下所示:
public interface ISomething extends JpaRepository<XYZ, Long>
{
@Query("FROM XYZ a WHERE a.eventDateTime < :before ORDER BY a.eventDateTime DESC")
List<XYZ> findXYZRecords(@Param("before") Date before, Pageable pageable);
}
当将可分页作为参数发送时,这应该可以解决问题。 例如,要获取前10个记录,您需要将可分页设置为此值:
new PageRequest(0, 10)
答案 3 :(得分:21)
新版本的Spring Data JPA与另一个名为Evans的模块列表具有使用关键字Top20
和First
限制查询结果的功能,
所以你现在可以写
了List<User> findTop20ByLastname(String lastname, Sort sort);
或
List<User> findTop20ByLastnameOrderByIdDesc(String lastname);
或单个结果
List<User> findFirstByLastnameOrderByIdDesc(String lastname);
答案 4 :(得分:12)
我的最佳选择是原生查询:
@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);
答案 5 :(得分:5)
new PageRequest(0,10)
在较新的Spring版本中不起作用(我正在使用2.2.1.RELEASE
)。基本上,构造函数有一个附加参数,类型为Sort
。此外,构造函数为protected
,因此您必须使用其子类之一或调用其of
静态方法:
PageRequest.of(0, 10, Sort.sort(User.class).by(User::getFirstName).ascending()))
您还可以忽略使用Sort
参数,并隐式使用默认排序(按pk等排序):
PageRequest.of(0, 10)
您的函数声明应如下所示:
List<User> findByUsername(String username, Pageable pageable)
函数将为:
userRepository.findByUsername("Abbas", PageRequest.of(0,10, Sort.sort(User.class).by(User::getLastName).ascending());
答案 6 :(得分:4)
使用@QueryHints也是可行的。示例bellow使用org.eclipse.persistence.config.QueryHints#JDBC_MAX_ROWS
@Query("SELECT u FROM User u WHERE .....")
@QueryHints(@QueryHint(name = JDBC_MAX_ROWS, value = "1"))
Voter findUser();
答案 7 :(得分:4)
如果您的课程@Repository
延长JpaRepository
,您可以使用以下示例。
int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();
getContent返回List<Transaction>
。