编程语言
首页 > 编程语言> > java-具有规范,分页和条件fetch-join的Spring Data JPA存储库

java-具有规范,分页和条件fetch-join的Spring Data JPA存储库

作者:互联网

我正在使用具有规范和分页功能的Spring Data JPA存储库为实体列表实现搜索/过滤服务.我正在尝试减少查询数量(n 1个问题)并使用标准获取机制来获取嵌套数据.

我有两个实体类:

@Entity
@Table(name = "delegations")
public class Delegation {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;

    @ManyToOne
    private Customer customer;

    // more fields, getters, setters, business logic...

}

@Entity
@Table(name = "customers")
public class Customer {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;

    // more fields, getters, setters, business logic...
}

DTO过滤器类:

public class DelegationFilter {

    private String customerName;

    // more filters, getters, setters...
}

以及搜索/过滤服务:

public class DelegationService {
    public Page<Delegation> findAll(DelegationFilter filter, Pageable page) {
        Specifications<Delegation> spec = Specifications.where(
                customerLike(filter.getCustomerName())
        );
        return delegationRepository.findAll(spec, page);
    }

    public List<Delegation> findAll(DelegationFilter filter) {
        Specifications<Delegation> spec = Specifications.where(
                customerLike(filter.getCustomerName())
        );
        return delegationRepository.findAll(spec);
    }

    private Specification<Delegation> customerLike(String customerName) {
        return (root, query, cb) -> {
            Join<Delegation,Customer> join = (Join) root.fetch(Delegation_.customer);
            return cb.like(cb.lower(join.get(Customer_.name)), addWildCards(customerName.toLowerCase()));
        };
    }

    private static String addWildCards(String param) {
        return '%' + param + '%';
    }
}

问题:

当我调用findAll(DelegationFilter filter,Pageable page)时,出现异常:

org.springframework.dao.InvalidDataAccessApiUsageException: 
org.hibernate.QueryException: query specified join fetching, but the owner 
of the fetched association was not present in the select list

有办法解决这个问题吗?

findAll(DelegationFilter filter)(无分页的方法)的工作原理类似于魅力…仅使用join(无获取)也可以正常工作(即使有分页)

我知道JPQL有解决方案:
Spring-Data FETCH JOIN with Paging is not working
但我想坚持使用标准API …

我正在使用Spring Boot 1.4(spring 4.3.2,spring-data-jpa 1.10.2)和Hibernate 5.0.9

解决方法:

我遇到了同样的问题,并且找到了解决方法(source).

您可以在运行时检查查询的返回类型,以便如果它是Long(计数查询返回的类型),则可以加入,否则进行获取.在您的代码中它将如下所示:

...
private Specification<Delegation> customerLike(String customerName) {
    return (root, query, cb) -> {
        if (query.getResultType() != Long.class && query.getResultType() != long.class) {
          Join<Delegation,Customer> join = (Join) root.fetch(Delegation_.customer);
        } else {
          Join<Delegation,Customer> join = root.join(Delegation_.customer);
        }
        return cb.like(cb.lower(join.get(Customer_.name)), addWildCards(customerName.toLowerCase()));
    };
}
...

我知道它不是很干净,但这是我在ATM上遇到的唯一解决方案.

标签:spring-data-jpa,spring-data,hibernate,spring,java
来源: https://codeday.me/bug/20191118/2025978.html