我有两个实体:
工程师可能拥有任意数量的标签。标签与任意数量的工程师相关联。
@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? */
}
是否有一个查询可以完成这项工作,还是我们需要逐步迭代结果来过滤?
答案 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)