JpaSpecificationExecutor.findAll(规范arg0,Pageable arg1)返回重复项

时间:2016-02-04 10:17:28

标签: hibernate spring-data spring-data-jpa

我们正在使用spring-data-jpa-1.2.0.RELEASE.jar中的org.springframework.data.jpa.repository.JpaSpecificationExecutor.findAll(Specification arg0,Pageable arg1)。 已在PageRequest中设置了提取大小1000。 我们在数据库视图中有超过60000条记录。 单个客户可以拥有n条记录。 这意味着它将在60次提取中获得整个数据。 如果在一次阅读中挑选了客户数据,那么我们就是好的。

行客户

*********************** CASE 1

998客户A

999客户A

1000客户A

*********************** Page End

1001客户B

1002客户B

否则,如果客户数据分布在两次读取中,那么我们就会遇到严重的问题

行客户 ***********************案例2

998客户X

999客户X

1000客户X

**********************页面结束 -

1001客户X

1002客户X

在这种情况下,客户X的记录与数据库不一致。我们可以看到X客户的重复记录,这意味着客户X的一些原始行缺失。 我们从page.getContent()获得现有行的副本。但客户X的总体数量始终保持不变。

当案例1中没有重叠时,问题不会发生,并且使用sql developer从数据库直接读取总是给出正确的行。 代码中还提供了额外的排序,但删除了排序并进行了检查,结果仍然相同。 但是,如果读取的行数增加到非常大的值,即30000,这意味着只有2个读取,则只有客户的重复数据在第30和31页之间重叠。 如果数据库中的数据较少(300行),那么即使客户在2次读取中也没有问题,也没有问题。 对我来说有点困惑请给我一些提示。

1 个答案:

答案 0 :(得分:1)

在规范中的query.distinct(true)方法中使用toPredicate。然后它只会获取不同的结果。

示例:

public class CustomSpecification implements Specification<MyObject> {

        private MyCriteria criteria;

        public CustomSpecification(MyCriteria criteria) {
            this.criteria = criteria;
        }

        @Override
        public Predicate toPredicate(Root<MyObject> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
            Predicate myPredicate =...;
            query.distinct(true);
            return myPredicate;
        }
    }