作为只读视图的JPA辅助表--Hibernate仍尝试插入行 [英] JPA secondary table as read only view - hibernate still tries to insert rows

查看:130
本文介绍了作为只读视图的JPA辅助表--Hibernate仍尝试插入行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下实体:

  @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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆