2011-06-14 80 views
2

我試圖使用在下面的類(ES)的JPA2標準API做一個簡單的查詢:CriteriaBuilder.isEmpty上ElementCollection與JPQL方法

// 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聯接(標**)殺死了這一切。我不知道爲什麼表THING指定兩次(THING to, THING t1)

顯然我做錯了。但我不知道是什麼錯。

+1

這將是正常的Stackoverflow標記一個答案,如果它回答了你的問題,如果不是說你嘗試了它沒有成功等。 – DataNucleus 2011-06-24 15:45:03

回答

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實現。