Hibernate@ElementCollection映射与@Audited在更新时创建重复密钥冲突

Hibernate@ElementCollection映射与@Audited在更新时创建重复密钥冲突,hibernate,jpa,hibernate-mapping,hibernate-envers,Hibernate,Jpa,Hibernate Mapping,Hibernate Envers,我在使用hibernate映射和审计时遇到了一个问题。 我的java类与映射: @Entiy @Audited @Table(name = "farm_detail") public class FarmDetail { @Id private Long id; @ElementCollection @MapKeyColumn(name = "field_id") @Column(name = "remark") @CollectionTable(n

我在使用hibernate映射和审计时遇到了一个问题。 我的java类与映射:

@Entiy
@Audited
@Table(name = "farm_detail")
public class FarmDetail {
   @Id
   private Long id;

    @ElementCollection
    @MapKeyColumn(name = "field_id")
    @Column(name = "remark")
    @CollectionTable(name = "farm_detail_remark", joinColumns =    @JoinColumn(name = "farm_detail_id"))
    private Map<String, String> fieldRemarks = new HashMap<>();
   // Getter, Setter, etc
}
如果我想更新
字段备注
集合的任何条目,我会在
农场详情
备注表上得到一个重复的键错误。通过打开sql日志记录,我发现hibernate试图在aud表中插入两个条目:

Hibernate: 
    /* insert farm_detail_remark_AUD
        */ insert 
        into
            farm_detail_remark_aud
            (revtype, rev, farm_detail_id, remark, field_id) 
        values
            (?, ?, ?, ?, ?)
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [1] as [INTEGER] - [0]
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [2] as [INTEGER] - [1057]
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [3] as [BIGINT] - [110]
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [4] as [VARCHAR] - [Old remark]
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [5] as [VARCHAR] - [152]
和(此处仅参数绑定):

有没有办法解决这个问题,而不为备注创建额外的实体


我使用的是spring boot 1.5.7附带的hibernate 5.0.12。数据库是postgresql 9.5.6。

我对5.0.12和5.2.10进行了测试,在这两种情况下,为映射生成的表模式与您提供的不同。这是否可能是您最近升级Hibernate的遗留应用程序

例如,在H2上,在我的测试中创建的表显示以下内容:

create table farm_detail_remark_AUD (
  REV integer not null, 
  field_detail_id integer not null, 
  remark varchar(255) not null, 
  field_id varchar(255) not null, 
  REVTYPE tinyint, 
  primary key (REV, field_detail_id, remark, field_id)
)

因此,对于您的场景,无法生成重复的主键,因为
备注
列包含在主键索引中,避免了您面临的问题。

因此,您基本上是在事务中按键更新映射的值,结果是REVTYPE=2(DEL)与映射键的旧值相关,与映射键的新值相关的REVTYPE=0(ADD)。这不是遗留的,但我不让hibernate生成数据库架构。但是如果你迷路了,这是一个让hibernate去做的好建议。稍后,我将检查hibernate envers在每个修订版中对此类“重复”条目返回的内容。您知道这是在哪里记录的吗?我们没有任何特定的地方来描述或记录基于给定映射的模式。我们经常依赖的是
hibernate工具
,其中用户调用它来生成架构脚本,他们要么选择运行部分脚本,要么至少验证他们手动创建的内容是否正确。另一种选择是根据虚拟数据库或H2实例使用实体映射启动应用程序,并查看日志以查看作为替代执行的DDL语句。
21:20:58.193 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [1] as [INTEGER] - [2]
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [2] as [INTEGER] - [1057]
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [3] as [BIGINT] - [110]
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [4] as [VARCHAR] - [new remark]
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [5] as [VARCHAR] - [152]
create table farm_detail_remark_AUD (
  REV integer not null, 
  field_detail_id integer not null, 
  remark varchar(255) not null, 
  field_id varchar(255) not null, 
  REVTYPE tinyint, 
  primary key (REV, field_detail_id, remark, field_id)
)