15

次の EJB 構造があります。Animalとについては不思議に思わないでくださいInventory。これらのクラスは、単純化された方法で構造を示すためにここにあるだけです (更新:よりわかりやすい例を作成するためにクラス名を変更しました。 の別の実装はIdTagかもしれませんBarcodeId)。IdTagからAnimalまたはに逆の関係がないことに注意してください。 は一意でInventoryあると仮定しましょう。基準クエリを使用したポリモーフィック Hibernate オブジェクトの取得Hibernate ポリモーフィック クエリRfidTag.codeを読みましたが、これらの議論は私の質問に答えていないようです。

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

今、私はどちらAnimalInventoryをクエリしRfidTag.codeたい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;
}

残念ながら、次のエラーが発生します。

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

これは継承に関連していると思いますIdTag->RfidTagそして、Animalについてのみ知ってIdTagおり、RfidTag.code. このようなクエリは可能ですか?

4

1 に答える 1

10

EclipseLinkを使用している場合、解決策は簡単です。RfIdTagにキャストするパス基準を変更します。

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

Hibernateを使用している場合は、メソッドを次のように置き換えます。

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

これにより、「T」と「RfIdTag」の間に「結合」(「フィルター処理されたデカルト積」)が作成されます。

于 2011-07-13T14:59:29.090 に答える