JPA辅助表作为只读视图 - hibernate仍尝试插入行

car*_*mer 2 java hibernate jpa view

我有以下实体:

@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;

(...)
}
Run Code Online (Sandbox Code Playgroud)

如您所见,此实体使用表ONE和(只读)视图VIEW_TWO.当我持久化实体时,hibernate正在执行insert into view:

insert into VIEW_TWO (ONE_ID) values (?)
Run Code Online (Sandbox Code Playgroud)

它忽略了不可更新和不可插入的列进度(这很好),它仍然试图插入ONE_ID列的值.据我所知,注释@PrimaryKeyJoinColumn将所选列标记为insertable = false和updatable = false.

如何防止hibernate将行插入到辅助表(视图)中?

Ala*_*Hay 5

据我所知,注释将@PrimaryKeyJoinColumn所选列标记为insertable = false和updatable = false.

我不相信这可能是这样的情况:@SecondaryTable当它是一个真实的表而不是一个视图时,我们如何将记录插入?

由于既没有@SecondaryTable@PrimarykeyJoinColumn有防止插入的方法,所以看起来您的原始解决方案不起作用并且需要替代方案.

一种选择是将VIEW_TWO映射为@Entity您的类的链接,并将其CPBracket作为@OneToOne与级联选项设置为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();
    }
}
Run Code Online (Sandbox Code Playgroud)

第二种选择是使用非JPA兼容的Hibernate特定@Formula注释.

@Entity
@Table(name = "ONE")
public class CpBracket {

       @Formula("native sql query")
       private int someValue;
}
Run Code Online (Sandbox Code Playgroud)

2016年10月更新

我在Hibernate 4.3.10.Final和5.1.0.Final中重新考虑了这一点,并且可以将视图视为@SecondaryTable没有插入的视图:如果你有正确的映射.

场景1

加载实体以进行编辑,不要触摸映射到辅助表的任何字段.不会向辅助表发布更新

情景2

创建并保存新实体,不要设置映射到辅助表的任何字段.没有为辅助表发出插入

场景3

创建或更新实体,包括映射到辅助表的字段,以及此字段标记为insertable = false和updateable = false的位置.的插入到二次表仅取得了ID字段-the行为报道,在原来的问题.

原始问题中映射的问题在于辅助表字段是基本类型,因此在保存新实体时,Hibernate确实认为必须将记录写入辅助表,其值为零.

@Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;
Run Code Online (Sandbox Code Playgroud)

然后解决方案是用相应的包装器类型替换原语并将它们保留为null.然后,在保存新记录时,没有任何内容可写入辅助表,也不会进行插入:

@Column(name="progress", table="VIEW_TWO")
private Integer progress;
Run Code Online (Sandbox Code Playgroud)