2011-06-21 39 views
15

Tôi có cấu trúc EJB sau đây. Đừng thắc mắc về AnimalInventory, những lớp này chỉ có ở đây để chứng minh cấu trúc theo cách đơn giản (Cập nhật: Tôi đã sửa đổi tên lớp để xây dựng một ví dụ dễ hiểu hơn. Triển khai khác IdTag có thể là BarcodeId). Lưu ý rằng không có mối quan hệ nghịch đảo nào từ IdTag đến Animal hoặc Inventory và giả sử RfidTag.code là duy nhất. Tôi đọc Retrieving Polymorphic Hibernate Objects Using a Criteria QueryHibernate polymorphic query nhưng những cuộc thảo luận này dường như không trả lời được câu hỏi của tôi.Các tiêu chí đa hìnhKhông có mối quan hệ nghịch đảo

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; 
} 

Bây giờ tôi muốn truy vấn hoặc Animal hoặc Inventory cho một RfidTag.code nhất định như 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; 
} 

RDP tôi nhận được các errror sau:

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

Tôi cho rằng điều này có liên quan đến thừa kế IdTag ->RfidTagAnimal chỉ biết về IdTag và không phải là RfidTag.code. Các truy vấn như thế này có thể không?

+0

Tôi không chắc liệu đây có phải là vấn đề hay không, vì tôi chưa bao giờ sử dụng trình xây dựng tiêu chí chung, nhưng dường như với tôi, vấn đề không quá nhiều trong thừa kế nhưng nhiều hơn trong thực tế là đường dẫn bạn chạy phương thức .get ("code") là null. Ít nhất đó là những gì ngoại lệ. bạn chắc chắn from.join ("idTag") không trả về null .. Và bạn không cần thay đổi nó thành from.join ("IdTag") vì tên của bảng được định nghĩa bằng chữ "I". – peshkira

+0

Theo như tôi biết, 'from.join (" idTag ")' không tham chiếu tên của bảng nhưng tên của thuộc tính trong 'ItemWithIdTag'. – Thor

+0

yepp - đó là sự thật ... xin lỗi. tuy nhiên, bạn đã kiểm tra giá trị trả về của phương thức kết nối chưa; là nó không null. Bạn có thể đăng toàn bộ dấu vết ngăn xếp để xem ngoại lệ lồng nhau là gì không? – peshkira

Trả lời

9

Nếu bạn đang sử dụng EclipseLink, giải pháp rất đơn giản. Sửa đổi tiêu chí Đường dẫn để cast để RfIdTag:

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

Nếu bạn đang sử dụng Hibernate, thay thế phương pháp của bạn với:

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(); 
} 

Điều này làm cho một "tham gia" ("một sản phẩm Descartes lọc") giữa " T "và" RfIdTag ".

+0

Ấn tượng! Tôi đã xác minh điều này với ví dụ đơn giản và có thể xác nhận đây là câu trả lời đúng. Bây giờ tôi đã thêm nó vào thế giới thực. Cảm ơn rất nhiều vì đã trả lời! – Thor

Các vấn đề liên quan