0

我有两个实体:

  1. 工程师 - 有一组标签(比如技能集 - Java. .NET 等)
  2. 标签

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

@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’、‘Opensource’和‘Banking’的工程师”。查询应返回具有与其关联的所有标签的工程师。

我可以查询一个标签:

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? */
}

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

4

3 回答 3

1

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

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

您模拟了工程师与标签的一对多关系。因此,在标签表上,您会看到一个外键列engineer_id。即:标签与一位(且仅一位)工程师相关联。

您需要使用连接表为多对多关系建模。Engineer 实体类应该有一个用 装饰的 Tag 集合@ManyToMany,Tag 实体类应该有一个用 装饰的 Engineer 集合@ManyToMany

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

于 2013-09-10T07:01:03.660 回答
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();
}

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

于 2013-09-10T09:19:42.180 回答
0

您可以使用多个子选择,也可以使用计数。

见, https://en.wikibooks.org/wiki/Java_Persistence/Querying#Subselect.2C_querying_a_to_many_relationship_where_all_of_the_relations_are_in_a_list

于 2013-09-10T14:50:23.413 回答