作为只读视图的JPA辅助表--Hibernate仍尝试插入行 [英] JPA secondary table as read only view - hibernate still tries to insert rows
问题描述
我有以下实体:
@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_TWO(ONE_ID)values(?)
忽略不可更新和不可插入的列进度(即好),它仍然试图插入 ONE_ID 列的值。据我所知,注释@PrimaryKeyJoinColumn将选定列标记为 insertable = false 和 updatable = false 。
如何防止hibernate将行插入到辅助表(视图)中?
正如我所知,注释
@PrimaryKeyJoinColumn
将选定的
列标记为insertable = false且updatable = false。
我不认为这可能是这种情况:如果我们如何将记录插入到 @SecondaryTable
中,那么当它是一个实际的表时而不是视图?
既不是 @SecondaryTable
或 @PrimarykeyJoinColumn
有防止插入的方法,那么看起来您的原始解决方案不会起作用,并且需要替代方案。
一种选择是将VIEW_TWO映射为一个 @Entity
并链接到您的课程 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();
第二种选择是使用非JPA兼容,特定于Hibernate的 @Formula
注解。
@Entity
@Table(name =ONE)
public class CpBracket {
@Formula(native sql query)
private int someValue;
}
2016年10月更新
<我已经在Hibernate 4.3.10.Final和5.1.0.Final中重新讨论了这一点,并且可以在没有插入的情况下将视图作为 @SecondaryTable
:如果您的映射正确。
场景1
<加载一个实体进行编辑,不要触及映射到次表的任何字段。没有更新发布到辅助表格
情景2
创建并保存一个新的实体并且不设置映射到辅助表的任何字段。没有为辅助表格发布插页
情景3
创建或更新包含映射到辅助表的字段的实体,并且该字段标记为可插入= false且可更新= false。插入 仅用于ID字段的辅助表 - 原始问题中报告的行为。
映射问题原来的问题是辅助表字段是一个基本类型,因此当保存一个新的实体时,Hibernate会认为必须将一个记录写入辅助表的值为零。
@Column(name =progress,table =VIEW_TWO,updatable = false,insertable = false)
private int progress = 0;
然后解决方案是用相应的包装类型替换原语并将它们保留为空。然后,当保存一条新记录时,没有任何信息写入辅助表,并且不会插入:
@Column(name =progress,table =VIEW_TWO)
private整数进度;
I've got the following entity:
@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;
(...)
}
As you see, this entity uses table ONE and (read only) view VIEW_TWO. When I'm persisting the entity, hibernate is performing insert into view:
insert into VIEW_TWO (ONE_ID) values (?)
It is ignoring the non-updatable and non-insertable column progress (that's good) and it is still trying to insert value of ONE_ID column. As far as I know, the annotation @PrimaryKeyJoinColumn marks selected column as insertable=false and updatable=false.
How can I prevent hibernate from inserting rows into secondary table (view)?
解决方案
As far as I know, the annotation @PrimaryKeyJoinColumn
marks selected
column as insertable=false and updatable=false.
I do not believe this can be the case: how then do we get records inserted into the @SecondaryTable
when it is an actual table rather than a view?
As neither @SecondaryTable
or @PrimarykeyJoinColumn
have a means to prevent insert then it would appear that your original solution is not going to work and an alternative is required.
One option is to map VIEW_TWO as an @Entity
and link to your class CPBracket
as a @OneToOne
relationship with cascade options set to none.
@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();
}
}
The second option would be to use the non JPA compliant, Hibernate specific @Formula
annotation.
@Entity
@Table(name = "ONE")
public class CpBracket {
@Formula("native sql query")
private int someValue;
}
Update October 2016
I have revisited this in both Hibernate 4.3.10.Final and 5.1.0.Final and it is possible to have the view as a @SecondaryTable
without the insert: if you have the correct mappings.
Scenario 1
Load an entity for edit and do not touch any fields mapped to the secondary table. No update is issued to the secondary table
Scenario 2
Create and save a new entity and do not set any fields mapped to the secondary table. No insert is issued for the secondary table
Scenario 3
Create or update an entity including a field mapped to a secondary table and where this field is marked as insertable = false and updateable = false. An insert is made to the secondary table only for the ID field -the behaviour reported in the original question.
The issue with the mapping in the original question is the fact that the secondary table field is a primitive type and therefore when saving a new entity Hibernate does think a record has to be written to the secondary table with a value of zero.
@Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;
The solution then is to replace primitives with the corresponding wrapper types and leave them as null. Then when saving a new record there is nothing to write to the secondary table and no insert will be made:
@Column(name="progress", table="VIEW_TWO")
private Integer progress;
这篇关于作为只读视图的JPA辅助表--Hibernate仍尝试插入行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!