148

我正在尝试将 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);
}

我只需one (and only one)要从 otherObj 返回用户,但我找不到注释 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

4

8 回答 8

201

从 Spring Data JPA 1.7.0 (Evans release train) 开始。

您可以使用新引入的关键字TopFirst关键字来定义查询方法,如下所示:

findTop10ByLastnameOrderByFirstnameAsc(String lastname);

Spring Data 会自动将结果限制为您定义的数字(如果省略,则默认为 1)。请注意,结果的顺序在这里变得相关(通过OrderBy示例中的子句或通过将参数传递给Sort方法)。在涵盖Spring Data Evans 发布系列的新功能的博客文章或文档中了解更多信息。

对于以前的版本

Pageable为了只检索数据片段,Spring Data 使用了分页抽象,它在请求端带有一个接口,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排序信息以获得稳定的结果。否则,即使下面的数据没有更改,您也可能会触发两次查询并获得不同的结果。

于 2012-02-16T17:26:34.977 回答
115

如果您使用的是 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));
  }

}
于 2016-02-08T08:50:10.833 回答
30

有一种方法可以提供等效于“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)
于 2015-02-10T23:54:49.357 回答
26

使用 Spring Data Evans (1.7.0 RELEASE)

Spring Data JPA 的新版本与另一个模块列表一起称为Evans,具有使用关键字Top20First限制查询结果的功能,

所以你现在可以写

List<User> findTop20ByLastname(String lastname, Sort sort);

或者

List<User> findTop20ByLastnameOrderByIdDesc(String lastname);

或单个结果

List<User> findFirstByLastnameOrderByIdDesc(String lastname);
于 2014-10-19T09:38:58.160 回答
14

对我来说最好的选择是原生查询:

@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);
于 2016-12-07T18:56:11.937 回答
9

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());
于 2020-05-14T21:18:45.083 回答
6

也可以使用@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();
于 2015-08-26T08:12:59.950 回答
5

如果您的课程@Repository扩展JpaRepository,您可以使用下面的示例。

int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();

getContent 返回一个List<Transaction>.

于 2017-09-22T20:02:11.653 回答