我正在尝试将 Spring-Data-JPA 合并到我的项目中。让我困惑的一件事是如何通过注释实现 setMaxResults(n) ?
例如,我的代码:
public interface UserRepository extends CrudRepository<User , Long>
{
@Query(value="From User u where u.otherObj = ?1 ")
public User findByOtherObj(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
从 Spring Data JPA 1.7.0 (Evans release train) 开始。
您可以使用新引入的 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
配备了排序信息以获得稳定的结果。否则,即使下面的数据没有更改,您也可能会触发两次查询并获得不同的结果。
如果您使用的是 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));
}
}
Stream<User> ... {...} default Optional<User> ... { ...findAny() }
有一种方法可以提供等效于“a setMaxResults(n) by annotation”,如下所示:
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 条记录,您需要将 pageable 设置为此值:
new PageRequest(0, 10)
使用 Spring Data Evans (1.7.0 RELEASE)
Spring Data JPA 的新版本与另一个模块列表一起称为 Evans 具有使用关键字 Top20
和 First
来限制查询结果的功能,
所以你现在可以写
List
或者
List
或单个结果
List
Pageable
对象。查看春季文档
findFirstByLastnameOrderByIdDesc
) 的返回类型写为 Optional<User>
甚至只是 User
对我来说最好的选择是原生查询:
@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);
nativeQuery
注释参数之外,不要忽略。
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());
也可以使用@QueryHints。下面的示例使用 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();
@QueryHints({@QueryHint(name = org.hibernate.annotations.FETCH_SIZE, value = "1")})
尝试它,但别名:( 不起作用
如果您的类 @Repository
扩展了 JpaRepository
,您可以使用下面的示例。
int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();
getContent 返回一个 List<Transaction>
。
不定期副业成功案例分享
List
作为方法的返回类型,则不是这样。Top
和First
关键字不适用于使用@Query
注释的方法?只有那些使用基于方法名的查询生成?