我想将 find 方法与接口(interface)一起使用,而不是与实现一起使用。
这就是我的代码:
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: Unable to locate persister: interfaces.Goods at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3422) at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3365) at repository.JPAGoodsRepository.lambda$deleteGoods$2(JPAGoodsRepository.java:58) at play.db.jpa.DefaultJPAApi.lambda$withTransaction$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;
});
}
最佳答案
EntityManager
方法createQuery
您使用的声明为:
<T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass)
Class<T> resultClass
的唯一原因参数是推断T
的类型,这样你就可以写:
List<Goods> listOfGoods = em.createQuery("select g from Goods g where id=:id", Goods.class).getResultList();
没有收到编译器警告。 resultClass
参数当然不会告诉 entityManager
您正在查询哪种实体类型。这是由 select g from Goods g
完成的查询的一部分,顺便说一下,Goods
是实体 GoodsImpl
的别名(您可以使用 GoodsImpl
注释 @Entity(name = "Bads")
实体,并且 select b from Bads b
也可以)。
现在,如果我理解正确的话,您是在问为什么调用 em.find(entityClass, primaryKey)
当 Goods.class
时失败用于entityClass
。您可以在 EntityManager
的 javadoc 中找到答案,其中find
据说抛出:
IllegalArgumentException - if the first argument does not denote an entity type
毫不奇怪,实体类型是一个用@Entity
注释的类。 。
如果您问为什么这是它的实现方式,那么答案非常简单。一个接口(interface)可以由多个类实现。假设您有多个实现 Goods
的实体类,每个都有自己的表和自己的 id。这些不同实体之间的 id 没有理由不重叠。 JPA 如何知道您希望获得这些实体中的哪一个?
关于java - JPA:通过接口(interface)查找而不是实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46208959/