2009-11-03 1 views
0

Представьте, что у меня есть класс Debtor. С Hibernate, я буду определять класс так:Как сопоставить абстрактный класс или интерфейс в Hibernate HQL?

@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). Конечно, в каждой схеме таблица, в которой размещен список должников, имеет одно и то же имя. В дополнение к этому у них может не быть такой же структуры. Вот почему у меня есть x differents Debtor класс (где x - это число схем, которыми я управляю).

В случае, когда у меня есть две схемы различий, у меня будет два разных класса Debtor: DebtorOne и DebtorTwo. Как я хочу, чтобы облегчить мои разработки, я создал интерфейс (или абстрактный класс, это не меняет мою проблему здесь), которая реализуется как DebtorOne и DebtorTwo:

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] 

Если я изменить DAO, чтобы это:

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

, то это работает, но это относится только к DebtorOne схеме ...

Одно решение, которое я вижу, чтобы определить именованный запрос на DebtorOne и DebtorTwo классов и называем это именованный запрос от моего 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(); 
} 

Я не пробовал, но я думаю, что это будет работать ...

EDIT Я просто попробовал, это будет работать ... за исключением того, что NamedQuery должно быть названо по-разному для DebtorOne и DebtorTwo ...

Однако мне интересно, есть ли способ решить мою проблему без использования последнего решения?


Редактировать относительно первого ответа, который наводит на мысль использовать @MappedSuperclass. Эта аннотация кажется идеальным решением для меня, но я думаю, что я что-то забыл, так как я все еще получаю ту же ошибку.

Основной Debtor:

@MappedSuperclass 
public class Debtor { 

    @Id 
    @Column(name = "IDDEBTOR") 
    protected String idDebtor; // With getter and setter 

} 

один из расширенного Debtor класса:

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

... 

и в моей DAO:

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]

Что я пропустил на этот раз?

ответ

1

Я думаю, что это не возможно, с интерфейсом, но только с общим абстрактным базовым классом, который будет с аннотацией @MappedSuperclass (см Hibernate документации для получения дополнительной информации)

0

Я думаю, что для этой работы вам» d либо нужно на самом деле сопоставить таблицу Debtor с таблицей или использовать таблицу для стратегии класса (union-subclass). @MappedSuperClass, похоже, реализует очень рудиментарный механизм для копирования свойств и не будет работать, потому что вы не можете запрашивать экземпляры суперкласса.

Я беру его из ссылки, что у вас уже есть что-то на месте, чтобы избежать отображений DebtorTwo в спящей сессии для схемы DebtorOne (в противном случае запроса Debtor будет тянуть все записи, в том числе те из DebtorTwo таблицы, которые не было бы существовать). В этом случае следуйте за example from the documentation, чтобы сопоставить подкласс для любого случая.

Смежные вопросы