Неверный SQL для объекта представления с использованием аннотаций Hibernate

Я работаю над отображением спящего объекта для представления базы данных; когда я делаю запрос критериев против него, hibernate генерирует плохой SQL. Любая помощь в выяснении, в чем проблема с моим отображением, будет принята с благодарностью!

У меня есть две сопоставленные сущности, которые я пытаюсь получить из представления базы данных; у представления нет других столбцов, только FK каждого объекта. Один из этих FK может рассматриваться как первичный ключ, так как представление имеет строку для каждого первичного объекта. Так что моя схема БД для представления выглядит так:

primary(primary_id, some_other_fields)
history(history_id, primary_id, some_other_fields)
view_latest_status_history(primary_id, history_id)

Обратите внимание, что представление используется, потому что я хочу выбрать только самую последнюю историю для каждого основного, а не все сопоставленные записи истории. Вот объект, который я использую для представления с аннотациями сущностей:

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Table(name = "view_latest_status_history")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ViewLatestStatusHistoryRow implements Serializable {
    private Primary primary;
    private History history;

    /**
     * @return Returns the history.
     */
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
    @JoinColumn(name = "history_id", nullable = true)
    @AccessType("field")
    public History getHistory() {
        return history;
    }

    //equals() and hashCode() implementations are omitted

    /**
     * @return Returns the primary.
     */
    @Id
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
    @JoinColumn(name = "primary_id", nullable = false)
    @AccessType("field")
    public Primary getPrimary() {
        return primary;
    }
}

Оба объекта: Primary и History имеют полные аннотации рабочего объекта.

Мои критерии настройки:

criteria.add(Restrictions.in("primary", [collection of primary objects]));
criteria.setFetchMode("primary", FetchMode.JOIN);
criteria.setFetchMode("history", FetchMode.JOIN);

И (неправильный) сгенерированный SQL:

select this_.primary as primary78_1_, this_.primary_id as prim2_78_1_, primary2_.history_id as unique1_56_0_, ...history fields
from DB_CATALOG.dbo.view_latest_status_history this_ 
left outer join DB_CATALOG.dbo.history primary2_ on this_.primary_id=primary2_.primary_id 
where this_.specChange in (?, ?...)

Я мог бы испортить несколько вещей при редактировании специфики схемы БД нашего проекта, но дело в том, что первое поле в предложении 'select' неверно:

this_.primary (view_latest_status_history.primary) не является полем; поле должно называться primary_id. Я думаю, что это может иметь какое-то отношение к аннотации @Id в основном поле? Любые идеи, как это исправить? Если я удаляю @Id, я получаю сообщение об ошибке, сообщающее, что у сущности нет первичного ключа.

Обновить:

Я больше не отображаю вид как поле, используя нотацию таблицы соединений (как предложено ниже). Аннотации были пересмотрены следующим образом. Это решение правильно работает в HQL и генерирует ожидаемую схему, когда включена функция hbm2ddl, но я не проверял ее повторно с помощью запроса критериев.

@Entity
@Table(name = "view_latest_status_history")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class ViewLatestStatusHistoryRow implements Serializable {
    private String id;
    private Primary primary;
    private History history;

    /**
     * @return Returns the history.
     */
    @OneToOne(optional = true)
    @JoinColumn(name = "history_id", nullable = true)
    @AccessType("field")
    public History getHistory() {
        return history;
    }

    //equals() and hashCode() implementations are omitted

    @Id
    @Column(name = "primary_id", nullable = false)
    @Override
    @AccessType(value = "field")
    public String getId() {
        return id;
    }

    /**
     * @return Returns the primary.
     */
    @PrimaryKeyJoinColumn(name = "primary_id", referencedColumnName = "unique_id")
    @OneToOne(optional = false)
    @AccessType("field")
    public Primary getPrimary() {
        return primary;
    }
}

1 ответ

Решение

Это, безусловно, связано с @Id аннотация - primary_id в данном случае НЕ является первичным ключом. Также вы не можете реально иметь @Id и @ManyToOne в одном свойстве.

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

Другие вопросы по тегам