【问题标题】:Specification/Predicate to Search Nested Objects搜索嵌套对象的规范/谓词
【发布时间】:2017-07-16 20:47:25
【问题描述】:

我将 Spring Boot 与 Spring JPA 和 Specification Executor 一起使用。我的规范/谓词组合成功地搜索了我班级中的简单属性。但是,我在搜索里面的对象时遇到了困难。他们需要单独的规范吗?我有一个类,其中包含 2 个多对一映射类,并希望在同一类中搜索这些字段。

谓词实现

public Specification<User> getSpecification(SpecificationField field, Object searchCriteria){
    return new Specification<User>() {
    @Override
    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

    if(searchCriteria instanceof String){
        searchCriteria.toString().trim().toLowerCase();
    }

    switch(field){
    case USER_GROUP:    
        return cb.equal(cb.lower(root.<String> get("group").get("name")), searchCriteria);
    case USER_ROLE: 
        return cb.equal(cb.lower(root.<String> get("role").get("name")), searchCriteria);
    case USER_EMAIL: 
        return cb.equal(cb.lower(root.<String> get("email")), searchCriteria);
    case USER_FIRSTNAME: 
        return cb.equal(cb.lower(root.<String> get("firstName")), searchCriteria);
    case USER_LASTNAME: 
        return cb.equal(cb.lower(root.<String> get("lastName")), searchCriteria);
    case USER_USERNAME: 
        return cb.equal(cb.lower(root.<String> get("username")), searchCriteria);
    default:
        assert true;
        return null;
    }

用户类

@Id
@GeneratedValue
@Column(name = "USER_ID")
private Long id;

@Column(name = "USER_FIRSTNAME", nullable = false)
private String firstName;

@Column(name = "USER_LASTNAME", nullable = false)
private String lastName;

@Column(name = "USER_EMAIL", nullable = false, unique = true)
private String email;

@Column(name = "USER_USERNAME", nullable = false, unique = true)
private String username;

@Column(name = "USER_PASSWORD", nullable = false)
private String encryptedPassword;

@ManyToOne
@JoinColumn(name = "USER_ROLE", nullable = false)
private Role role;

@ManyToOne
@JoinColumn(name = "USER_GROUP", nullable = false)
private Group group;

角色类

@Id
@GeneratedValue
@Column(name = "ROLE_ID")
private Long id;

@Column(name = "ROLE_NAME", nullable = false, unique = true)
private String name;

团体课

@Id
@GeneratedValue
@Column(name = "GROUP_ID")
private Long id;

@Column(name = "GROUP_NAME", nullable = false, unique = true)
private String name;

@Column(name = "GROUP_TOKEN", nullable = false, unique = true)
private String token;

----------------------------------------------- ---------------------------------------

编辑:

想出了这个用于嵌套对象的 Predicate 实现。

Root<Group> group = query.from(Group.class);
Root<Role> role = query.from(Role.class);

switch(field){
case USER_GROUP:
    return cb.equal(cb.lower(group.<String> get("name")), searchCriteria);
case USER_ROLE: 
    return cb.equal(cb.lower(role.<String> get("name")), searchCriteria);

这工作得更好,但不是很好。我有可能的组名值 DEV、UAT 或 PROD。如果我提供其中任何一个,我将获得数据库中的所有用户。如果我不这样做,我不会让任何用户回来。如何对此嵌套对象的名称进行文本搜索?

谢谢。

【问题讨论】:

    标签: java jpa spring-data specifications predicate


    【解决方案1】:

    我自己找到了答案,但想与大家分享,以便它可以帮助其他有同样问题的人。

    @Override
    public Predicate toPredicate(Root<User> userRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
    
        switch(field){
        case USER_GROUP:
            Join<User, Group> groupJoin = userRoot.join("group");
            return cb.equal(cb.lower(groupJoin.<String> get("name")), searchCriteria);
        case USER_ROLE: 
            Join<User, Role> roleJoin = userRoot.join("role");
            return cb.equal(cb.lower(roleJoin.<String> get("name")), searchCriteria);
    

    使用 javax.persistence 库中的 Join 类,我可以使用相同的规范搜索类中的嵌套对象。

    【讨论】:

    • 我们能否有一种更通用的方式将其应用于所有实体?
    • JPA 规范只允许您在根中加入带有 Hibernate 映射的元素(据我所知)。这些是 ManyToOne ManyToMany 或 OneToMany 注释。
    • 你的意思是说我必须为我拥有的每个实体创建这个,为所有实体创建一个单独的 CriteriaBuilder?
    • 仅您需要高级搜索的实体。 JPA 动态查询可用于大多数简单的搜索。
    • 如果我的内部对象说这个问题的角色是数据(注释)而不是实体(注释)呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 2011-02-23
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    相关资源
    最近更新 更多