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