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

StackOverflow https://stackoverflow.com/questions/1441671

Вопрос

Я работаю над отображением объектов в режиме гибернации для представления базы данных;когда я выполняю запрос критериев к нему, 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;
    }
}

Как первичный объект, так и объект Истории имеют полные аннотации к рабочим объектам.

Настройка моих критериев:

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, но я не тестировал его повторно с помощью запроса criteria.

@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;
    }
}
Это было полезно?

Решение

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top