【问题标题】:CriteriaBuilder.isEmpty on an ElementCollection vs. JPQL approachElementCollection 与 JPQL 方法上的 CriteriaBuilder.isEmpty
【发布时间】:2011-06-14 07:46:18
【问题描述】:

我正在尝试对以下类使用 JPA2 标准 API 进行简单查询:

// a lot of imports

@Entity
public class Thing {
    enum Type { FIRST, SECOND, THIRD };

    @SequenceGenerator(name = "Thing_SeqGen", sequenceName = "Thing_Id_Seq", initialValue = 1000)
    @Id
    @GeneratedValue(generator = "Thing_SeqGen")
    private int id;

    private String name = "name";

    @Enumerated(EnumType.STRING)
    @ElementCollection(targetClass = Thing.Type.class)
    @CollectionTable(name = "TYPES", joinColumns = { @JoinColumn(referencedColumnName = "ID", name = "TYPE_ID") })

    private Set<Thing.Type> typeSet = new HashSet<Thing.Type>();
    public static void main(final String[] args) {
        new Thing().start();
    }

    public void start() {
        final Thing firstThing = new Thing();
        firstThing.setName("First one");
        firstThing.setTypeSet(EnumSet.of(Thing.Type.FIRST));
        final Thing firstAndSecondThing = new Thing();
        firstAndSecondThing.setName("Test2");
        firstAndSecondThing.setTypeSet(EnumSet.of(Thing.Type.FIRST, Thing.Type.SECOND));
        final Thing bareThing = new Thing();
        bareThing.setName("Test3");

        final EntityManagerFactory emf =  Persistence.createEntityManagerFactory("sandbox");
        final EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();
        em.persist(firstThing);
        em.persist(firstAndSecondThing);
        em.persist(bareThing);
        em.getTransaction().commit();

        em.getTransaction().begin();
        final CriteriaBuilder cb = em.getCriteriaBuilder();
        final CriteriaQuery<Thing> c = cb.createQuery(Thing.class);
        final Root<Thing> root = c.from(Thing.class);
        final Join<Thing, Set<Thing.Type>> typeJoin = root.join("typeSet");

        c.select(root).distinct(true).where(cb.isEmpty(typeJoin));

        final List<Thing> results = em.createQuery(c).getResultList();

        em.getTransaction().commit();
    }

    // getter/setter methods omitted
}

我要查询的内容:查找所有没有排版的东西。

完成这项工作的 JPQL 是:

select t from Thing t where t.typeSet is empty

JPQL 查询返回一个预期的结果。条件查询不返回任何结果。 CriteriaBuilder 已创建:

SELECT DISTINCT t0.ID, t0.NAME FROM THING t0, TYPES t1 WHERE (((SELECT COUNT(t2.ID) FROM THING t2 WHERE (t1.TYPE_ID = t0.ID)) = 0) **AND (t1.TYPE_ID = t0.ID)**)

最后一个 theta-join(标记为 **)将其全部杀死。而且我不知道为什么表THING 被指定了两次(THING to, THING t1)

显然我做错了。但我不知道是什么问题。

【问题讨论】:

  • 如果 Stackoverflow 回答了您的问题,则在 Stackoverflow 上标记答案是正常的,如果不是说您尝试过但没有成功等等。

标签: api jpa criteria eclipselink


【解决方案1】:

我猜问题是您尝试在 Criteria 案例中进行显式连接,而在 JPQL 中您没有。所以省略加入并做类似的事情

Metamodel model = emf.getMetamodel();
ManagedType thingType = model.managedType(Thing.class);
CollectionAttribute typeSetAttr = thingType.getCollection("typeSet");
c.select(root).distinct(true).where(cb.isEmpty(root.get(typeSetAttr)));

这应该会转换为与您发布的相同的 JPQL ... 或者至少对于 DataNucleus JPA 实现是这样。

【讨论】:

    猜你喜欢
    • 2014-01-12
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 2023-03-13
    • 2017-12-20
    • 2012-08-21
    • 2019-04-30
    相关资源
    最近更新 更多