使用JPA CriteriaBuilder生成查询,其中属性为列表或为空(Using JPA Cri

2019-10-20 19:34发布

我试图使用JPA CriteriaBuilder生成名为“TestContact”有一个实体的查询的多到多用所谓的“SystemGroup”其中,此属性联接所谓的“团体”另一个实体加盟。 查询的目的是从这里的“组”属性为列表或为空的“TestContact”实体检索记录。

我正在使用的代码如下:

public List<TestContact> findWithCriteriaQuery(List<SystemGroup> groups) {

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<TestContact> cq = cb.createQuery(TestContact.class);
    Root<TestContact> testContact = cq.from(TestContact.class);
    cq.select(testContact);

    Path<List<SystemGroup>> groupPath = testContact.get("groups");

    // cq.where(groupPath.in(groups));
    // cq.where(cb.isEmpty(groupPath));
    cq.where(cb.or(cb.isEmpty(groupPath), groupPath.in(groups)));

    TypedQuery<TestContact> tq = em.createQuery(cq);

    return tq.getResultList();
}

问题是这样的查询只返回结果,其中组是在列表中的“组”,但由于某种原因,是不是也返回结果,其中组是空的(即没有在连接表中没有条目)

如果我改变where子句cq.where(cb.isEmpty(groupPath)); 那么查询正确返回结果,其中组是空的。

如果我改变where子句cq.where(groupPath.in(groups)); 那么该查询返回正确的结果,其中组是在列表中的“组”。

我不明白的是,为什么当我尝试使用CriteriaBuilder或方法的结果不包括在记录中,其中基团是在列表或者是空的这两个谓词结合起来。

该集团在“TestContact”实体属性的声明如下

@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name = "TEST_CONTACT_GROUPS", joinColumns = { @JoinColumn(name = "CONTACT_ID", referencedColumnName = "CONTACT_ID") }, inverseJoinColumns = { @JoinColumn(name = "GROUP_ID", referencedColumnName = "GROUP_ID") })
private List<SystemGroup> groups;

JPA提供者是的EclipseLink 2.5.0的Java EE应用服务器GlassFish的是4,数据库是Oracle 11gR2的。

任何人都可以请指出我要去哪里错了吗?

更新

我试着从@克里斯的建议,但Eclipse是返回以下错误Join<List<SystemGroup>> groupPath = testContact.join("groups", JoinType.LEFT)

的类型参数的注册数目不正确; 它不能与参数进行参数>

纵观JavaDoc中Join它说的类型参数...

ž - 联接,X的源类型 - 目标类型的联接

我试图Join<TestContact, SystemGroup> groupPath = testContact.join("groups", JoinType.LEFT); 然后使Eclipse来回报下列错误cb.isEmpty

绑定不匹配:类型CriteriaBuilder的一般方法的isEmpty(表达)是不适用的参数(加入)。 推断出的类型SystemGroup不是用于有界参数的有效替代>

Answer 1:

所述testContact.get( “基团”); 条款迫使从testContact内加入到组,筛选出不群testContacts。 你需要指定一个左外连接,并用它在你的isEmpty和条款。

Root<TestContact> testContact = cq.from(TestContact.class);
cq.select(testContact);

Join<TestContact, SystemGroup> groupPath = testContact.join("groups", JoinType.LEFT);
cq.where(cb.or(cb.isEmpty(testContact.get("groups")), groupPath.in(groups)));

我通常是指https://en.wikibooks.org/wiki/Java_Persistence/Criteria#Join的例子



文章来源: Using JPA CriteriaBuilder to generate query where attribute is either in a list or is empty