JPA:查询目标也是列表的列表中的所有项目
我有两个实体: Engineer-有一组标记,如skillsets-Java。NET等。 标签 工程师可以有任意数量的标签。标签与任意数量的工程师关联JPA:查询目标也是列表的列表中的所有项目,jpa,Jpa,我有两个实体: Engineer-有一组标记,如skillsets-Java。NET等。 标签 工程师可以有任意数量的标签。标签与任意数量的工程师关联 @Entity public class Engineer implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(nullable = false, length = 12) private S
@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? */
}
是否有一个查询可以完成这项工作,或者我们是否需要逐步迭代结果以进行筛选
工程师可以有任意数量的标签。标签与任意数量的工程师关联
@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 */
}
您的实体设计与上述要求相矛盾
您模拟了与标记具有一对多关系的工程师。因此,在标记表上,您将看到一个外键列engineer_id。即:标记与一个且仅与一个engineer关联
您需要使用联接表对多对多关系进行建模。工程师实体类应具有用@manytomy修饰的标记集合,标记实体类应具有用@manytomy修饰的工程师集合
使用标签类上的Engineer集合,您可以实现searchMindsByTags函数我想到的第一件事是,您可以使用以下内容构造查询:
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();
}
它的快速示例需要一些测试。您可以使用多个子选择,也可以使用计数 看,,
1。我想你需要@manytoman映射。2.为什么不在第二次查询中对标记列表中的所有元素进行排序,并针对每个条件使用和?我将尝试使用许多,但您能否告诉我在这种情况下使用的查询是什么?您不需要条件查询,只需在每个标记对象上组合engineer集合即可。当然,这是效率较低的,因为每次访问engineer集合时,它都会转换为1个SQL,因此没有看到将其转换为多个SQL的好处。我们还可以反复浏览这个列表。需要明确的是,标记实体不会将工程师作为属性。如果不将其设置为多对多,那么如何满足标记与任意数量的工程师相关联的要求?一旦一个标签被附加到一个工程师身上,你就不能再附加到另一个工程师身上了。工程师id FK列只能引用1个工程师。我认为这是行不通的。我测试了一个直截了当的查询:从工程师中选择e加入e.tags,其中tag.name='Drools'和tag.name='Eclipse'。tag.name怎么可能同时拥有两个名称?抱歉,我修复了我的方法抱歉,我发现了另一个错误,必须再次修复,现在应该可以工作了。