代码之家  ›  专栏  ›  技术社区  ›  Romain Linsolas

如何在Hibernate HQL中映射抽象类或接口?

  •  0
  • Romain Linsolas  · 技术社区  · 15 年前

    想象一下我有一个 Debtor 班级。在Hibernate中,我将这样定义类:

    @Entity
    @Table(name = "T_DEBTOR")
    public class Debtor {
    
        @Id
        @Column(name = "ID_DEBTOR")
        private String idDebtor;
        ...
    

    我的刀看起来像:

    public class DebtorDaoImpl implements DebtorDao {
    
        @PersistenceContext
        private EntityManager em;
    
        @SuppressWarnings("unchecked")
        public List<Debtor> findAllDebtors() {
            Query q = em.createQuery("select d from Debtor d");
            return (List<Debtor>) q.getResultList();
        }
    

    这很管用。但是,我处于一种需要访问不同模式的配置中(如所指出的 here )。当然,在每个模式中,承载债务人列表的表没有相同的名称。除此之外,它们可能没有完全相同的结构。所以我有 X 不同的 债务人 类(何处) X 是我操作的架构数)。

    如果我有两种不同的模式,我会有两种不同的模式 债务人 班级: DebtorOne DebtorTwo . 为了简化开发过程,我创建了一个接口(或抽象类,它不会改变我在这里的问题),由两者实现 德托龙 债务人2 :

    public interface Debtor {
    
        String getIdDebtor();
    
    }
    

    还有:

    @Entity
    @Table(name = "T_DEBTOR_ONE")
    public class DebtorOne implements Debtor {
    
        @Id
        @Column(name = "ID_DEBTOR")
        private String idDebtor;
        ...
    

    如果让我的DAO保持原样,我会从休眠中得到以下错误:

    Caused by: org.hibernate.hql.ast.QuerySyntaxException: Debtor is not mapped [select d from Debtor d]
    

    如果我把刀换成这个:

        public List<Debtor> findAllDebtors() {
            Query q = em.createQuery("select d from DebtorOne d");
            return (List<Debtor>) q.getResultList();
        }
    

    然后它就工作了,但它是特定于 德托龙 模式…

    我看到的一个解决方案是在 德托龙 德托二 从我的DAO中调用这个命名查询。 换句话说:

    @Entity
    @Table(name = "T_DEBTOR_ONE")
    @NamedNativeQueries( { @NamedNativeQuery(name = "findAllDebtors", query = "select d from DebtorOne d") })
    public class DebtorOne implements Debtor {
    

    在刀中:

    @SuppressWarnings("unchecked")
    public List<Debtor> findAllDebtors() {
        Query q = em.createNamedQuery("findAllDebtors");
        return (List<Debtor>) q.getResultList();
    }
    

    我还没试过,但我想它会起作用…

    编辑 我刚试过,这会奏效的…除了那个 NamedQuery 必须以不同的名称命名 德托龙 德托二

    然而,我想知道是否有一种方法可以解决我的问题而不使用后一种解决方案?


    编辑 关于第一个答案,建议使用 @MappedSuperclass . 这个注释对我来说似乎是一个完美的解决方案,但是我想我忘了一些事情,因为我仍然得到同样的错误。

    主要 债务人 :

    @MappedSuperclass
    public class Debtor {
    
        @Id
        @Column(name = "IDDEBTOR")
        protected String idDebtor; // With getter and setter
    
    }
    

    其中一个扩展 债务人 班级:

    @Entity
    @Table(name = "DEBTOR_ONE")
    public class DebtorOne extends Debtor {
    
    ...
    

    在我的刀里:

    public List<Debtor> findAllDebtors() {
        return (List<Debtor>) em.createQuery("select d from Debtor d").getResultList();
    }
    

    仍然返回错误 Caused by: org.hibernate.hql.ast.QuerySyntaxException: Debtor is not mapped [select d from Debtor d]

    这次我错过了什么?

    2 回复  |  直到 15 年前
        1
  •  1
  •   lweller    15 年前

    我认为这在接口上是不可能的,但只能在公共抽象基类上实现,该类将用@mappedsuperclass进行注释(有关详细信息,请参阅Hibernate文档)。

        2
  •  0
  •   wds    15 年前

    我认为要想让这个工作,你要么要实际地绘制 Debtor 表到表或使用每个类的表策略(联合子类)。 @MappedSuperClass 似乎只实现了一种非常基本的机制来复制属性,但由于无法查询超类的实例,因此无法工作。

    我从链接中得知你已经有了一些可以避免映射的东西 DebtorTwo 在架构的休眠会话中 DebtorOne (否则查询 债务人 会把所有的记录,包括 德托二 不存在的表)。在这种情况下,请遵循 example from the documentation 为这两种情况映射子类。