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

时间:2009-11-03 09:02:16

标签: java hibernate hql

想象一下,我有一个Debtor课程。使用Hibernate,我将定义类:

@Entity
@Table(name = "T_DEBTOR")
public class Debtor {

    @Id
    @Column(name = "ID_DEBTOR")
    private String idDebtor;
    ...

我的DAO将会是这样的:

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)。当然,在每个模式中,托管debtor列表的表都没有相同的名称。除此之外,它们可能没有完全相同的结构。这就是为什么我有 x 不同Debtor类(其中 x 是我操作的模式数量)。

如果我有两个不同的模式,我将有两个不同的Debtor类:DebtorOneDebtorTwo。 由于我想简化我的开发,我创建了一个由DebtorOneDebtorTwo实现的接口(或一个抽象类,它不会改变我的问题):

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原样,我从Hibernate得到以下错误:

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

如果我将DAO更改为:

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

然后它可以工作,但它特定于DebtorOne架构...

我看到的一个解决方案是在DebtorOneDebtorTwo类上定义命名查询,并从我的DAO调用此命名查询。 换句话说:

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

并在DAO中:

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

我还没试过,但我认为它会起作用......

编辑我刚试过,这会有效......除了NamedQueryDebtorOne的{​​{1}}名称必须不同......

但是,我想知道是否有办法在不使用后一种解决方案的情况下解决我的问题?


关于第一个答案的

编辑,建议使用DebtorTwo。这个注释对我来说似乎是一个完美的解决方案,但我想我忘了一些东西,因为我仍然得到同样的错误。

@MappedSuperclass

Debtor

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

Debtor

在我的DAO中:

@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(); }

这次我错过了什么?

2 个答案:

答案 0 :(得分:1)

我认为这不可能使用接口,但只能使用一个公共抽象基类,它将使用@MappedSuperclass注释(有关详细信息,请参阅Hibernate文档)

答案 1 :(得分:0)

我认为为了实现这一点,您必须实际将Debtor表映射到表或使用每个类策略的表(union-subclass)。 @MappedSuperClass似乎只是实现了一个非常基本的机制来复制属性,因为你无法查询超类的实例而无法工作。

我从您已经拥有某些内容的链接中获取它,以避免在DebtorTwo的模式的hibernate会话中映射DebtorOne(否则查询Debtor将拉入所有记录,包括DebtorTwo表中不存在的表。在这种情况下,请按照example from the documentation映射两种情况的子类。