Неверный SQL для объекта представления с использованием аннотаций Hibernate - PullRequest
1 голос
/ 18 сентября 2009

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

1 голос
/ 18 сентября 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...