Tho*_*hor 15 java inheritance jpa criteriaquery
我有以下EJB结构.不要怀疑Animal和Inventory,这些类只是在这里以简化的方式演示结构(更新:我修改了类名以构造一个更好的可理解的例子.另一个实现IdTag可能是a BarcodeId).请注意,IdTag与Animal或之间没有反比关系Inventory,我们假设它RfidTag.code是唯一的.我阅读使用Criteria Query和Hibernate多态查询检索多态Hibernate对象,但这些讨论似乎没有回答我的问题.
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;
}
Run Code Online (Sandbox Code Playgroud)
现在,我想无论是查询Animal或Inventory对给定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;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我得到以下错误:
javax.ejb.EJBException: java.lang.IllegalArgumentException:
Unable to resolve attribute [code] against path [null]
Run Code Online (Sandbox Code Playgroud)
我假设这与继承有关IdTag- > RfidTag并且Animal只知道IdTag而不是RfidTag.code.像这样的查询可能吗?
Edu*_*sta 10
如果您使用的是EclipseLink,解决方案很简单.修改路径条件以强制转换为RfIdTag:
Path<Object> path = ((Path) from.join("idTag").as(RfIdTag.class)).get("code");
Run Code Online (Sandbox Code Playgroud)
如果您使用的是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();
}
Run Code Online (Sandbox Code Playgroud)
这在"T"和"RfIdTag"之间形成"连接"("过滤的笛卡尔积").
| 归档时间: |
|
| 查看次数: |
4733 次 |
| 最近记录: |