java - JPA:通过接口(interface)查找而不是实现

标签 java hibernate jpa playframework annotations

我想将 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/

相关文章:

java - 使用 Hibernate 时数据库的成熟度有多重要

java - jpa多个双向多对一关系到同一个字段

spring - SQL 错误 : 23503, SQLState : 23503 in SpringBoot 2. 1.4.RELEASE 应用程序

java - 无法在 Eclipse 中作为 Java 应用程序运行,即使有正确的 main() 类

java - Hibernate 与连接表的一对多关系与连接表中的附加列

java - JPA+SQLite问题

java - JPA EntityManager.merge() 尝试将更新级联到已删除的实体

java - java中正则表达式的神奇日期

java - 在maven项目中使用intellij idea制作jar,MANIFEST.MF错误

java - 无法使用 AJAX 响应作为文件名(而非内容)