Spring JPA/Hibernate返回随机的最后一页?

huangapple go评论72阅读模式
英文:

Spring JPA/Hibernate returns random last page?

问题

我最近将一个服务从:

  • JDK8 -> JDK11
  • Spring Boot 1.5 -> Spring Boot 2.3

从那以后,一个集成测试以一种奇怪的方式失败了,当执行查询(分页)时出现问题。从100个结果中,即5页,第5页总是随机选择。

结果看起来像这样:

第0页(ids [0, 19])

[SomeObject@... 'inttest_log_device_0', ...]
[SomeObject@... 'inttest_log_device_1', ...]
[SomeObject@... 'inttest_log_device_2', ...]
[SomeObject@... 'inttest_log_device_3', ...]
[SomeObject@... 'inttest_log_device_4', ...]
[SomeObject@... 'inttest_log_device_5', ...]
[SomeObject@... 'inttest_log_device_6', ...]
[SomeObject@... 'inttest_log_device_7', ...]
[SomeObject@... 'inttest_log_device_8', ...]
[SomeObject@... 'inttest_log_device_9',...]
[SomeObject@... 'inttest_log_device_10', ...]
[SomeObject@... 'inttest_log_device_11', ...]
[SomeObject@... 'inttest_log_device_12', ...]
[SomeObject@... 'inttest_log_device_13', ...]
[SomeObject@... 'inttest_log_device_14', ...]
[SomeObject@... 'inttest_log_device_15', ...]
[SomeObject@... 'inttest_log_device_16', ...]
[SomeObject@... 'inttest_log_device_17', ...]
[SomeObject@... 'inttest_log_device_18', ...]
[SomeObject@... 'inttest_log_device_19', ...]

页面1-3继续如上。

然而最后一页(#4)不同(预期ids [80, 99]):

[SomeObject@... 'inttest_log_device_25', ...]
[SomeObject@... 'inttest_log_device_94', ...]
[SomeObject@... 'inttest_log_device_0', ...]
[SomeObject@... 'inttest_log_device_31', ...]
[SomeObject@... 'inttest_log_device_62', ...]
[SomeObject@... 'inttest_log_device_13', ...]
[SomeObject@... 'inttest_log_device_69', ...]
[SomeObject@... 'inttest_log_device_33', ...]
[SomeObject@... 'inttest_log_device_64', ...]
[SomeObject@... 'inttest_log_device_52', ...]
[SomeObject@... 'inttest_log_device_86', ...]
[SomeObject@... 'inttest_log_device_24', ...]
[SomeObject@... 'inttest_log_device_16', ...]
[SomeObject@... 'inttest_log_device_22', ...]
[SomeObject@... 'inttest_log_device_89', ...]
[SomeObject@... 'inttest_log_device_50', ...]
[SomeObject@... 'inttest_log_device_57', ...]
[SomeObject@... 'inttest_log_device_92', ...]
[SomeObject@... 'inttest_log_device_29', ...]
[SomeObject@... 'inttest_log_device_15', ...]

执行的代码是:

someRepository.findAll(predicate, pageable);

其中 repository 简单地扩展了 Spring 的 JpaRepositoryQuerydslPredicateExecutorpredicate 是一个带有一些过滤条件的 BooleanBuilder

此代码此前一直运行得非常完美。但自从升级后开始出问题。

英文:

I have recently upgraded a service from:

  • JDK8 -> JDK11
  • Spring Boot 1.5 -> Spring Boot 2.3

Since then, an integration test fails in a weird way, such that when a query is executed (pageable). From the 100 results i.e. 5 pages, the 5th page is always a random selection.

The result looks looks like this:

Page 0 (ids [0, 19])

[SomeObject@... 'inttest_log_device_0', ...]
[SomeObject@... 'inttest_log_device_1', ...]
[SomeObject@... 'inttest_log_device_2', ...]
[SomeObject@... 'inttest_log_device_3', ...]
[SomeObject@... 'inttest_log_device_4', ...]
[SomeObject@... 'inttest_log_device_5', ...]
[SomeObject@... 'inttest_log_device_6', ...]
[SomeObject@... 'inttest_log_device_7', ...]
[SomeObject@... 'inttest_log_device_8', ...]
[SomeObject@... 'inttest_log_device_9',...]
[SomeObject@... 'inttest_log_device_10', ...]
[SomeObject@... 'inttest_log_device_11', ...]
[SomeObject@... 'inttest_log_device_12', ...]
[SomeObject@... 'inttest_log_device_13', ...]
[SomeObject@... 'inttest_log_device_14', ...]
[SomeObject@... 'inttest_log_device_15', ...]
[SomeObject@... 'inttest_log_device_16', ...]
[SomeObject@... 'inttest_log_device_17', ...]
[SomeObject@... 'inttest_log_device_18', ...]
[SomeObject@... 'inttest_log_device_19', ...]

Pages 1-3 continue as above.

However the last page (#4) is different (expected ids [80, 99]) :

[SomeObject@... 'inttest_log_device_25', ...]
[SomeObject@... 'inttest_log_device_94', ...]
[SomeObject@... 'inttest_log_device_0', ...]
[SomeObject@... 'inttest_log_device_31', ...]
[SomeObject@... 'inttest_log_device_62', ...]
[SomeObject@... 'inttest_log_device_13', ...]
[SomeObject@... 'inttest_log_device_69', ...]
[SomeObject@... 'inttest_log_device_33', ...]
[SomeObject@... 'inttest_log_device_64', ...]
[SomeObject@... 'inttest_log_device_52', ...]
[SomeObject@... 'inttest_log_device_86', ...]
[SomeObject@... 'inttest_log_device_24', ...]
[SomeObject@... 'inttest_log_device_16', ...]
[SomeObject@... 'inttest_log_device_22', ...]
[SomeObject@... 'inttest_log_device_89', ...]
[SomeObject@... 'inttest_log_device_50', ...]
[SomeObject@... 'inttest_log_device_57', ...]
[SomeObject@... 'inttest_log_device_92', ...]
[SomeObject@... 'inttest_log_device_29', ...]
[SomeObject@... 'inttest_log_device_15', ...]

The executed code is:

someRepository.findAll(predicate, pageable);

Where the repository simply extends Spring's JpaRepository and QuerydslPredicateExecutor. The predicate is a BooleanBuilder with some filter criteria.

The code furthermore always worked perfectly well. It just started making problems once I've upgraded.

答案1

得分: 3

没有明确的排序,基本上你就要看数据库管理系统返回什么。使用分页时,你应该始终有明确的排序。

你可以通过向传递的“Pageable”添加“Sort”来实现这一点。

Pageable pageable = PageRequest.of(0, 1, Direction.ASC, "id");

这样做应该能达到效果。

英文:

Without an explicit ordering, you are basically at the perils of DBMS what it returns. When using paging you should always have an explicit ordering.

You can do this by adding a Sort to the Pageable you pass in.

Pageable pageable = PageRequest.of(0, 1, Direction.ASC, "id);

Something like that should do the trick.

huangapple
  • 本文由 发表于 2020年8月17日 15:45:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63446646.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定