【问题标题】:How can I add and build dynamic predicates to subquery using jpa specification?如何使用 jpa 规范向子查询添加和构建动态谓词?
【发布时间】:2019-08-07 12:39:27
【问题描述】:

我正在尝试使用 JPA 规范构建动态子查询。如何向子查询添加谓词并构建它?

例如,我将有 2 个表: 用户和用户卡:

@Entity
    @Table(name = "users", schema = "someschema")
    public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String surName;
    private String email;

    @OneToMany
    private List<Usercard> usercardList;

//other methods...
}

@Entity
@Table(name = "usercard", schema = "someschema")
public class Usercard {
    @Id
    private Long id;
    private String account;
    private String value;

    @ManyToOne
    private User user;

//other methods...
}

我有我的回购:

@Repository
public interface UserRepository extends JpaRepository<User, Long>, 
JpaSpecificationExecutor<User> {}

并尝试构建类似的东西:

public List<User> findByPredicate(String email) {
    return userRepository.findAll((Specification<User>) (root, 
        criteriaQuery, criteriaBuilder) -> {

        List<Predicate> predicates = new ArrayList<>();
        if (email != null) {
        predicates.add(criteriaBuilder.and(criteriaBuilder.equal( 
                                       root.get("email"), email)));
        }
        return criteriaBuilder.and(predicates.toArray(new 
                Predicate[predicates.size()]));
    });
}

但对于带有谓词的子查询。

我试过这样的方法:

public List<User> findByUsercardAccount(String email, String account) {
    return userRepository.findAll(new Specification<User>() {
        @Override
        public Predicate toPredicate(Root<User> root, CriteriaQuery<?> 
            criteriaQuery, CriteriaBuilder criteriaBuilder) {

            Subquery<Usercard> subquery = 
                criteriaQuery.subquery(Usercard.class);
            Root<Usercard> subRoot = subquery.from(Usercard.class);
            List<Predicate> predicates = new ArrayList<>();

            //predicates for Users table
            predicates.add(criteriaBuilder.and(criteriaBuilder.equal( 
                       root.get("email"), email)));
            //predicates for Usercard table
            predicates.add(criteriaBuilder.equal(subRoot.get("account"), 
                       account));


            return criteriaBuilder.and(predicates.toArray(new 
                        Predicate[predicates.size()]));
        }
    });
}

因此,我需要一种在几个表中进行动态搜索的方法,在这些表中我可以为动态查询和动态子查询传递参数。如果有任何帮助,我将不胜感激。

【问题讨论】:

  • 我看到了这个。但是,不幸的是,对于如何将动态谓词添加到子查询的问题没有答案。静态的 - 可能是动态的 - 没有。

标签: java spring jpa spring-data


【解决方案1】:

找到了这个解决方案:

public List<User> findByUsercardAccount(String account, String email) {
    return userRepository.findAll((Specification<User>) (root, criteriaQuery, criteriaBuilder) -> {

        Subquery<User> subquery = criteriaQuery.subquery(User.class);
        Root<Usercard> subRoot = subquery.from(Usercard.class);

        List<Predicate> predicates = new ArrayList<>();
        List<Predicate> subPredicates = new ArrayList<>();

        if (account != null)
            subPredicates.add(criteriaBuilder.equal(subRoot.get("account"), account));

        if (email != null)
            predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("email"), email)));

        subquery.select(subRoot.get("id")).where(subPredicates.toArray(new Predicate[predicates.size()]));

        predicates.add(criteriaBuilder.exists(subquery));

        return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
    });
}

}

所以,我创建了子根和子查询,添加了一些限制(子谓词)并将它们作为谓词传递给主根。

【讨论】:

    猜你喜欢
    • 2019-12-25
    • 2017-09-26
    • 2022-11-21
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多