Java JPA:通过接口而不是实现查找
我希望将find方法与接口一起使用,而不是与实现一起使用 这就是我的代码:Java JPA:通过接口而不是实现查找,java,hibernate,jpa,playframework,annotations,Java,Hibernate,Jpa,Playframework,Annotations,我希望将find方法与接口一起使用,而不是与实现一起使用 这就是我的代码: public Goods findGoods(Long goodsId) { return this.jpaApi.withTransaction(()->{ Goods goods = null; try{ EntityManager em = this.jpaApi.em(); Query query = em.create
public Goods findGoods(Long goodsId) {
return this.jpaApi.withTransaction(()->{
Goods goods = null;
try{
EntityManager em = this.jpaApi.em();
Query query = em.createQuery("select g from Goods g where id=:id", Goods.class);
query.setParameter("id", goodsId);
goods = (Goods) query.getSingleResult();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return goods;
});
}
我的实体:
@Entity(name = "Goods")
@Table(name = "GOODS")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class GoodsImp implements Goods, Serializable {
..
}
我的界面:
@JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, property = "type",
use = Id.NAME, defaultImpl = GoodsImp.class, visible = true)
@JsonSubTypes({ @Type(value = ProductImp.class, name = "product"),
@Type(value = ServiceImp.class, name = "service") })
@ImplementedBy(GoodsImp.class)
public interface Goods {
..
}
错误:
java.lang.IllegalArgumentException:无法找到persister:interfaces.Goods
位于org.hibernate.internal.SessionImpl.find(SessionImpl.java:3422)
位于org.hibernate.internal.SessionImpl.find(SessionImpl.java:3365)
位于repository.JPAGoodsRepository.lambda$deleteGoods$2(JPAGoodsRepository.java:58)
atplay.db.jpa.DefaultJPAApi.lambda$和事务$3(DefaultJPAApi.java:197)
我的疑问是,如果我使用的查询语句与接口配合良好,为什么会出现这个问题
这项工作:
@Override
public Collection<Goods> getAllGoods() {
return this.jpaApi.withTransaction(() -> {
Collection<Goods> goods = null;
try {
EntityManager em = this.jpaApi.em();
Query query = em.createQuery("Select g from Goods g", Goods.class);
goods = query.getResultList();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return goods;
});
}
@覆盖
公共集合getAllGoods(){
返回此.jpaApi.withTransaction(()->{
收款货物=空;
试一试{
EntityManager em=this.jpaApi.em();
Query Query=em.createQuery(“从货物g中选择g”,货物.class);
货物=query.getResultList();
}捕获(例外e){
//TODO:处理异常
e、 printStackTrace();
}
退货;
});
}
您使用的EntityManager
方法createQuery
声明为:
<T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass)
没有得到编译器警告。resultClass
参数是当然不会告诉entityManager
您要查询的实体类型。这是通过查询的select g from Goods g
部分完成的,顺便提一下,Goods
是实体goodsiml
的别名(您可以使用@entity(name=“Bads”)注释goodsiml
实体和从Bads b中选择b
也可以工作)
现在,如果我理解正确,您会问为什么调用em.find(entityClass,primaryKey)
失败,而Goods.class
用于entityClass
。您可以在javadoc中找到EntityManager
的答案,其中find
被称为抛出:
IllegalArgumentException-如果第一个参数不表示实体类型
毫不奇怪,实体类型是一个用@entity
注释的类
如果你问为什么它是这样实现的,那么答案很简单。一个接口可以由几个类实现。假设您有多个实体类实现了商品
,每个实体类都有自己的表和自己的id。没有理由不让id在这些不同的实体之间重叠。JPA如何知道您希望获得这些实体中的哪一个?您使用的EntityManager
方法createQuery
声明为:
<T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass)
没有得到编译器警告。resultClass
参数是当然不会告诉entityManager
您要查询的实体类型。这是通过查询的select g from Goods g
部分完成的,顺便提一下,Goods
是实体goodsiml
的别名(您可以使用@entity(name=“Bads”)注释goodsiml
实体和从Bads b中选择b
也可以工作)
现在,如果我理解正确,您会问为什么调用em.find(entityClass,primaryKey)
失败,而Goods.class
用于entityClass
。您可以在javadoc中找到EntityManager
的答案,其中find
被称为抛出:
IllegalArgumentException-如果第一个参数不表示实体类型
毫不奇怪,实体类型是一个用@entity
注释的类
如果你问为什么它是这样实现的,那么答案很简单。一个接口可以由几个类实现。假设您有多个实体类实现了商品
,每个实体类都有自己的表和自己的id。没有理由不让id在这些不同的实体之间重叠。JPA应该如何知道您希望得到哪些实体? JPA API不认为接口值得持久化处理。数据核JPA确实允许JPQL,但不知道任何其他的,并且你在那里进入供应商扩展,所以,我只能使用JPQL中的接口,但不在.find方法中。正如我所说的,JPA不考虑接口,所以如果遵守规范,就不能使用它们,只有我知道的1个供应商支持它们。但是你没有使用它。为什么接口在getAllGoods()中工作?在你的例子中,你没有使用接口,你已经将实体名黑客化为接口类的名称。这就是JPQL所使用的,并将其解释为GoodsImp。因此,问题的标题是非此即彼。JPA API不认为接口值得持久化处理。数据核JPA确实允许JPQL,但不知道任何其他的,并且你在那里进入供应商扩展,所以,我只能使用JPQL中的接口,但不在.find方法中。正如我所说的,JPA不考虑接口,所以如果遵守规范,就不能使用它们,只有我知道的1个供应商支持它们。但是你没有使用它。为什么接口在getAllGoods()中工作?在你的例子中,你没有使用接口,你已经将实体名黑客化为接口类的名称。这就是JPQL所使用的,并将其解释为GoodsImp。所以问题的标题是毫无意义的伟大的答案,这就是我想要的。谢谢。因此,我的选项是,使用带别名的TypedQuery或使用实体本身的find方法。非常感谢。回答得很好,这就是我想要的。谢谢。因此,我的选项是,使用带别名的TypedQuery或使用实体本身的find方法。谢谢。