我有以下实体:
@Entity
@Table(name = "ONE")
@SecondaryTable(name = "VIEW_TWO", pkJoinColumns = @PrimaryKeyJoinColumn(name="ONE_ID"))
public class CpBracket {
@Id
private Long id;
@Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;
(...)
}
如您所见,此实体使用表格 ONE 和(只读)视图 VIEW_TWO 。当我持久化实体时,hibernate正在执行insert into view:
insert into VIEW_TWO (ONE_ID) values (?)
它忽略了不可更新和不可插入的列进度(这很好),它仍在尝试插入 ONE_ID 列的值。据我所知,注释@PrimaryKeyJoinColumn将所选列标记为 insertable = false 和 updatable = false 。
如何防止hibernate将行插入二级表(视图)?
答案 0 :(得分:5)
据我所知,注释
@PrimaryKeyJoinColumn
标记为已选中 column as insertable = false和updatable = false。
我不相信会出现这种情况:当@SecondaryTable
是实际的表而不是视图时,我们如何将记录插入@SecondaryTable
?
由于@PrimarykeyJoinColumn
或@Entity
都没有办法阻止插入,因此您的原始解决方案似乎不起作用,并且需要替代方案。
一种选择是将VIEW_TWO映射为CPBracket
,并将@OneToOne
作为@Entity
@Table(name ="VIEW_TWO")
private CpBracketSummaryData(){
}
@Entity
@Table(name = "ONE")
public class CpBracket {
@OneToOne
@PrimaryKeyJoinColumn
private CPBracketSummaryData summaryData;
public int getSomeValue(){
return summaryData.getSomeValue();
}
}
关系链接到级联选项设置为无。
@Formula
第二个选项是使用非JPA兼容的Hibernate特定@Entity
@Table(name = "ONE")
public class CpBracket {
@Formula("native sql query")
private int someValue;
}
注释。
@SecondaryTable
我在Hibernate 4.3.10.Final和5.1.0.Final中重新考虑了这一点,如果你有正确的映射,可以将视图设为@Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;
而不使用insert: / em>的
情景1
加载实体以进行编辑,不要触摸映射到辅助表的任何字段。没有更新发布到辅助表
场景2
创建并保存新实体,不要设置映射到辅助表的任何字段。没有为辅助表发布插入
场景3
创建或更新实体,包括映射到辅助表的字段,以及此字段标记为insertable = false和updateable = false的位置。插件 仅针对ID字段对辅助表进行插入 - 原始问题中报告的行为。
原始问题中映射的问题是辅助表字段是基本类型,因此在保存新实体时,Hibernate确实认为必须将记录写入辅助表,其值为零。
@Column(name="progress", table="VIEW_TWO")
private Integer progress;
然后解决方案是用相应的包装器类型替换基元并将它们保留为null。然后,当保存新记录时,没有任何内容可写入辅助表,也不会进行插入:
select ref_id
from ref r
join matchset s
on s.value = r.value
group by ref_id
having count(*)=(select count(*) from matchset)