我正在为数据库视图处理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;
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
@JoinColumn(name = "history_id", nullable = true)
@AccessType("field")
public History getHistory() {
return history;
}
@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 (?, ?...)
在编辑我们项目的db模式的细节时,我可能会弄乱一些东西,但重点是“select”子句中的第一个字段是错误的:
这个主字段(view_latest_status_history.primary)不是字段;该字段应该称为主字段。我认为这可能与主字段上的@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;
@OneToOne(optional = true)
@JoinColumn(name = "history_id", nullable = true)
@AccessType("field")
public History getHistory() {
return history;
}
@Id
@Column(name = "primary_id", nullable = false)
@Override
@AccessType(value = "field")
public String getId() {
return id;
}
@PrimaryKeyJoinColumn(name = "primary_id", referencedColumnName = "unique_id")
@OneToOne(optional = false)
@AccessType("field")
public Primary getPrimary() {
return primary;
}
}