2011-06-21 22 views
15

Aşağıdaki EJB yapısına sahibim. Animal ve Inventory hakkında merak etme, bu sınıflar yalnızca yapıyı basitleştirilmiş bir şekilde göstermek için buradadır (Güncelleme: Daha iyi anlaşılabilir bir örnek oluşturmak için sınıf adlarını değiştirdim. IdTag'un başka bir uygulaması BarcodeId olabilir). IdTag ile Animal veya Inventory arasında ters bir ilişki olmadığını ve RfidTag.code'un benzersiz olduğunu varsayalım. Retrieving Polymorphic Hibernate Objects Using a Criteria Query ve Hibernate polymorphic query'u okudum, ancak bu tartışmalar sorumu yanıtlamıyor gibi görünüyor. Bunun ile ilgili olduğunuPolimorfik Kriterler Ters ilişki gösterilmeden sorgulama

javax.ejb.EJBException: java.lang.IllegalArgumentException: 
Unable to resolve attribute [code] against path [null] 

varsayalım:

public interface ItemWithIdTag 
{ 
    IdTag getIdTag(); 
    void setIdTag(IdTag idTag); 
} 

@Entity public class Animal implements ItemWithIdTag,Serializable 
{ 
    @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; 

    @OneToOne(cascade = CascadeType.ALL) 
    private IdTag idTag; 
} 

@Entity public class Inventory implements ItemWithIdTag,Serializable 
{ 
    @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; 

    @OneToOne(cascade = CascadeType.ALL) 
    private IdTag idTag; 
} 

@Entity @Table(name = "IdTag") @Inheritance(strategy= InheritanceType.JOINED) 
public class IdTag implements Serializable 
{ 
    @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; 
    private Date created; 
} 

@Entity @Table(name = "RfidTag") 
public class RfidTag extends IdTag implements Serializable 
{ 
    private String code; 
} 

Şimdi ben şu errror olsun Unfortuately Animal ejb = bean.fEntityWithRfidTag(Animal.class,"myRfIdCode");

public <T extends ItemWithIdTag> T fOwner(Class<T> type, String catName) 
{ 
    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); 
    CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(type); 
    Root<T> from = criteriaQuery.from(type); 

    Path<Object> path = from.join("idTag").get("code"); 

    CriteriaQuery<T> select = criteriaQuery.select(from); 
    select.where(criteriaBuilder.equal(path, catName)); 

    TypedQuery<T> q = em.createQuery(select); 
    T result = (T)q.getSingleResult();} 
    return result; 
} 

gibi belirli bir RfidTag.code için ya Animal veya Inventory sorgulamak istiyorum IdTag ->RfidTag ve Animal yalnızca,hakkında bilgi sahibive RfidTag.code. Bunun gibi sorgular mümkün mü?

+0

Asla bu sorun olup olmadığından emin değilim, çünkü genel kriterler oluşturucu kullanmadım, ama bana öyle geliyor ki, bu problem mirasta çok fazla değil ama daha çok sizin koştuğunuz yolda .get ("code") yöntemi boş. En azından istisna durum böyle. from.join ("idTag") 'un boşa dönmediğinden emin misiniz? Ve tablonun ismi bir "I" ile tanımlandığından, onu ("IdTag") from.join olarak değiştirmenize gerek yoktur. – peshkira

+0

Bildiğim kadarıyla, 'from.join (" idTag ")' tablonun adını değil, özniteliğin 'ItemWithIdTag'daki adını belirtmez. – Thor

+0

yepp - bu doğru ... üzgünüm. Ancak, birleştirme yönteminin dönüş değerini kontrol ettiniz; boş değil mi Yuvalanmış istisnanın ne olduğunu görmek için tüm yığın izini gönderir misiniz? – peshkira

cevap

9

EclipseLink kullanıyorsanız, çözüm basittir. RfIdTag yayın yapmak için Yol kriterlerini değiştirin:

public static <T extends ItemWithIdTag> T fOwner(Class<T> type, String catName) { 
    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); 
    CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(type); 
    Root<T> fromType = criteriaQuery.from(type); 
    Root<RfIdTag> fromRfId = criteriaQuery.from(RfIdTag.class); 

    Path<Object> pathCode = fromRfId.get("code"); 
    Path<Object> pathIdTagType = fromType.get("idTag"); 
    Path<Object> pathIdTagRfId = fromRfId.get("id"); 

    CriteriaQuery<T> select = criteriaQuery.select(fromType); 
    select.where(
      criteriaBuilder.equal(pathCode, catName), 
      criteriaBuilder.equal(pathIdTagType, pathIdTagRfId)); 

    TypedQuery<T> q = em.createQuery(select); 
    return q.getSingleResult(); 
} 

Buna "arasında ("filtrelenmiş bir kartezyen ürünü") "katılmak" yapar: Eğer Hibernate kullanıyorsanız

Path<Object> path = ((Path) from.join("idTag").as(RfIdTag.class)).get("code"); 

ile yönteminizi değiştirin T "ve" RfIdTag ".

+0

Etkileyici! Bunu basitleştirilmiş örnekle doğruladım ve doğru cevap olduğunu doğrulayabilirim. Şimdi bunu gerçek dünyaya eklemem gerekiyor. Cevap verdiğiniz için çok teşekkürler! – Thor