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

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

我有两个实体:

Engineer-有一组标记,如skillsets-Java。NET等。 标签 工程师可以有任意数量的标签。标签与任意数量的工程师关联

@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怎么可能同时拥有两个名称?抱歉,我修复了我的方法抱歉,我发现了另一个错误,必须再次修复,现在应该可以工作了。