ChatGPT解决这个技术问题 Extra ChatGPT

用于 Spring-Data-JPA 注释的 setMaxResults?

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


M
Matteo Molnar

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

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

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 配备了排序信息以获得稳定的结果。否则,即使下面的数据没有更改,您也可能会触发两次查询并获得不同的结果。


谢谢,但我仍然希望有一个“基于注释”的解决方案。因为在这种情况下,“Page / Pageable”太过分了。并且客户端必须创建一个 Pageable/Page 来检索“唯一一个”结果......使用起来非常不友好。看来你是负责 Spring-Data 的,希望你能进一步研究这个问题:stackoverflow.com/questions/9276461/…。你能确认它是否是 Spring-Data 的错误吗?
+ 这行得通,谢谢,但基于注释的解决方案在新版本中会更好
如果我们想要一个有限的查询,这里会触发一个计数查询,这是完全没有必要的。
如果您使用 List 作为方法的返回类型,则不是这样。
我认为,TopFirst 关键字不适用于使用 @Query 注释的方法?只有那些使用基于方法名的查询生成?
W
Wim Deblauwe

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

有一种方法可以提供等效于“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)

如果您使用的是 Pagable 则其返回 Page 而不是 List
@Arundev 错误 - List 完美运行(并避免了 a previous comment 中已经提到的不必要的 count 查询)
C
Community

使用 Spring Data Evans (1.7.0 RELEASE)

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

所以你现在可以写

List findTop20ByLastname(String lastname, Sort sort);

或者

List findTop20ByLastnameOrderByIdDesc(String lastname);

或单个结果

List findFirstByLastnameOrderByIdDesc(String lastname);


可选<用户> findFirstByLastnameOrderByIdDesc(String lastname);
获得top20结果后,当我使用分页转到网站的下一页时,如何获得接下来的20个结果?
@kittu,这当然是另一个问题,但您需要传递一个 Pageable 对象。查看春季文档
如果指定了 FIRST,为什么他们让该方法返回一个该死的 List ?
最好将最后一个方法 (findFirstByLastnameOrderByIdDesc) 的返回类型写为 Optional<User> 甚至只是 User
G
Grigory Kislin

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

@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);

不确定 Hibernate 是否支持限制:forum.hibernate.org/viewtopic.php?f=9&t=939314
打破了整个概念!最好使用 EntityManager 代替!
@Code.IT 我传播 KISS 概念。除了添加的 JPA nativeQuery 注释参数之外,不要忽略。
@GKislin 比你必须重命名你的方法,比如 findLimitOneByOtherObj。此外,如果 other_obj 不是唯一的,您也忘记添加会导致错误结果的 OrderBy。否则,在唯一列上的 where 语句应该足够了,没有限制
LIMIT 关键字不是 hibernate 而是 postgres/mysql
A
Abbas Hosseini

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());

k
kraken

也可以使用@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 的文档也很薄。见下文。 docs.spring.io/spring-data/jpa/docs/1.7.1.RELEASE/reference/…
IIRC,不保证会遵循查询提示。这只是将“友好建议”传递给实施的一种方式。
我在 Hibernate 中使用 @QueryHints({@QueryHint(name = org.hibernate.annotations.FETCH_SIZE, value = "1")}) 尝试它,但别名:( 不起作用
org.hibernate.annotations.FETCH_SIZE 它的获取大小,它不是限制,不是最大结果。冬眠不能
ᗩИᎠЯƎᗩ

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

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

getContent 返回一个 List<Transaction>


如果我在查询中有 2 个 where 条件,例如 transactionRepository.findByFirstNameAndLastName(firstname, lastname) 怎么办?它会起作用吗?我收到此异常 org.springframework.data.mapping.PropertyReferenceException: No property create found for type Board。