【问题标题】:JPA secondary table as read only view - hibernate still tries to insert rowsJPA 辅助表作为只读视图 - 休眠仍尝试插入行
【发布时间】:2016-09-06 12:56:32
【问题描述】:

我有以下实体:

@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。当我持久化实体时,休眠正在执行插入视图:

insert into VIEW_TWO (ONE_ID) values (?)

它忽略了不可更新和不可插入的列 progress(这很好),它仍在尝试插入 ONE_ID 列的值。据我所知,@PrimaryKeyJoinColumn 注释将选定列标记为 insertable=falseupdatable=false

如何防止休眠将行插入辅助表(视图)?

【问题讨论】:

  • 这里有一个副本,没有接受的答案。 stackoverflow.com/questions/34208122/…
  • 作为替代方案,您可以映射为没有级联的@OneToOne 关系,而不是@SecondaryTable。我认为这可以解决问题。
  • 如果你要持久化一个对象,如果你想阻止它插入,你希望SecondaryTable中的对象条目来自哪里?
  • @AlanHay,不可能使用一对一的关系映射整数。
  • 其他解决方案是使用 Hibernate 特定的非 JPA @Formula 列。 @SecondaryTable 不行。

标签: java hibernate jpa view


【解决方案1】:

据我所知,注释@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 确实认为必须将记录写入辅助表,其值为 0。

@Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;

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

@Column(name="progress", table="VIEW_TWO")
private Integer progress;

【讨论】:

  • 哇,感谢您在半年后仍调查此案。我设法将逻辑从视图移动到 java 代码并避免使用@SecondaryTable
猜你喜欢
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
  • 2017-08-03
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 2017-03-08
相关资源
最近更新 更多