JPA:查询列表中所有项目,其中目标也是列表

时间:2013-09-10 06:21:54

标签: jpa

我有两个实体:

  1. 工程师 - 有一组标签(比如技能组 - Java..NET等)
  2. 标签
  3. 工程师可能拥有任意数量的标签。标签与任意数量的工程师相关联。

    @Entity
    public class Engineer implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @Id
        @Column(nullable = false, length = 12)
        private String id;
    
        @Column(length = 100)
        private String name;
    
        @OneToMany(fetch = FetchType.EAGER)
        List<Tag> tags;
    
        /* Getters and Setters */
    }
    
    @Entity
    public class Tag implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @Id
        private int id;
    
        @Column(length = 50)
        private String name;
    
        /* Getters and Setters */
    }
    

    现在,我想查询拥有与之关联的标签列表的工程师。例如 - “查询带有标签'Java','开源'和'银行'的工程师”。该查询应返回具有与之关联的所有标记的工程师。

    我可以查询一个标签:

    public List<Engineer> searchMindsByTags(String tag) {
        Query q = em.createQuery("SELECT e FROM Engineer e WHERE '" + tag
                + "' = ANY(SELECT tag.name FROM e.tags tag)");
        return (List<Engineer>) q.getResultList();
    }
    

    我需要的是:

    public List<Engineer> searchMindsByTags(List<String> tags) {
        /* Which query goes here? */
    }
    

    是否有一个查询可以完成这项工作,还是我们需要逐步迭代结果来过滤?

3 个答案:

答案 0 :(得分:1)

  

工程师可能拥有任意数量的标签。标签与任意数量的工程师相关联。

您的实体设计与上述要求相矛盾。

您建模工程师与Tag有一对多的关系。因此,在标记表上,您将看到外键列engineer_id。即:标签与一个(并且仅为1个)工程师相关联。

您需要使用连接表对关系建模多少。工程师实体类应该使用@ManyToMany装饰标签集合,标签实体类应该有一个用@ManyToMany装饰的工程师集合。

使用Tag类上的Engineer集合,您可以实现searchMindsByTags函数

答案 1 :(得分:0)

我想到的第一件事是你可以用这样的东西构建你的查询:

public List<String> searchMindsByTags(List<String> tags)
{

    String queryString = "SELECT e FROM Engineer e ";
    List<Tag> tagobjects=null;
    if (tags != null && !tags.isEmpty()) {
        Query q = entityManager.createQuery("Select t from tag t where t.name IN :tags");
        q.setParameter("tags", tags);
        tagobjects = q.getResultList();
        queryString += " WHERE ";
        for (int i = 0; i < tagobjects.size(); i++) {
            if (i != 0) {
                queryString += "AND ";
            }
            queryString += "?" + (i + 1) + " member of e.tags";
        }
    }
    Query q = entityManager.createQuery(queryString);
    if (tagobjects != null && !tagobjects.isEmpty()) {
        for (int i = 0; i < tagobjects.size(); i++) {
            q.setParameter((i + 1), tagobjects.get(i));
        }
    }
    return (List<Engineer>) q.getResultList();
}

它的快速示例需要一些测试。

答案 2 :(得分:0)