【问题标题】:Wrong insert order at JPA/Hibernate OneToOne bidirectional relationship with the same PKJPA / Hibernate OneToOne双向关系与相同PK的错误插入顺序
【发布时间】:2015-07-14 22:24:59
【问题描述】:

我正在尝试在共享相同 PK 的两个实体之间建立OneToOne 关系:

+----------------------------------+   +----------------+-----------------+        
|              Item                |   |              Stats               |
+----------------+-----------------+   +----------------+-----------------+
| reference (PK) |  other data...  |   | reference (PK) |  other data...  |
+----------------+-----------------+   +----------------+-----------------+
|          ABCD  |      ...        |   |          ABCD  |      ...        |
|           XYZ  |      ...        |   |           XYZ  |      ...        |
+----------------+-----------------+   +----------------+-----------------+

其中Stats.referenceItem.reference 的FK:

alter table Stats 
    add constraint FK_8du3dv2q88ptdvthk8gmsipsk 
    foreign key (reference) 
    references Item;

此结构由以下带注释的类生成:

@Entity
public class Item {
   @Id
   private String reference;

   @OneToOne(mappedBy = "item", optional = false)
   @Cascade({CascadeType.SAVE_UPDATE})
   @Fetch(FetchMode.SELECT)
   private Stats stats;

   // ...
}

@Entity
public class Stats {

   @Id
   @OneToOne
   @JoinColumn(name = "reference")
   @Fetch(FetchMode.SELECT)   
   private Item item;  

   // ...
}

一个新的Item 创建如下:

Item item = new Item();
item.setReference("ABC");
Stats stats = new Stats();
stats.setItem(item);
item.setStats(stats);
session.save(item);

我的问题是当我执行session.save(item) 时,INSERT 语句的顺序是错误的。 Hibernate 首先尝试插入Stats 表而不是Item,导致FK 约束错误。

我该如何解决这个问题?提前致谢。

【问题讨论】:

  • @boutaya 的回答很好,也给你的 forgein 键一个不同的名字。你也已经把它作为主键了。

标签: java hibernate jpa


【解决方案1】:

由于您的班级 Stats 拥有该关联,请尝试这样做:

stats.setItem(item);
session.save(stats)

【讨论】:

  • 我试过了,但问题依旧。此外,我认为我需要保存Item,因为它与其他OneToOne 关系具有相同的PK (Item -> Stats) (Item -> Stock) (Item -> x) 与本示例中描述的相同问题.无论如何,感谢您的回答。
  • 它应该工作!尝试像 Shahzeb 所说的那样重命名外键:@JoinColumn(name = "otherName")
  • 应该可以,但是不行。发生同样的错误,我在日志中看到 insert into Stats 语句和约束错误。最后我找到了解决办法。我已将注释更改为:@JoinColumn(name = "reference", referencedColumnName = "reference"),它可以工作。谢谢。
【解决方案2】:

由于项目和状态之间存在一对一的关系,并且项目的 stats 键为 FK,因此您的实体对象应如下所示

物品{

@OneToOne
@JoinColumn(name = "stat_id", nullable=false) //incase if you allow null
private stats stats

}

在stats实体中不需要添加关系注解,因为我们在Item中定义了

保存时,您只需保存项目实体,还会插入统计信息

item.setStats(stats);
session.save(item);

如果您想分别保存统计数据和项目,

然后您将级联类型定义为 DETACH 用于统计

 Class Item{

    @OneToOne(cascade=CascadeType.DETACH)
    @JoinColumn(name = "stat_id", nullable=false) //incase if you allow null
    private stats stats
}

【讨论】:

    【解决方案3】:

    Stats实体中的@JoinColumn注解不完整,必须指定属性referencedColumnName

    公共抽象 java.lang.String referencedColumnName

    (可选)此外键引用的列的名称 列。

    @Entity
    public class Stats {
    
       @Id
       @OneToOne
       @JoinColumn(name = "reference", referencedColumnName = "reference")
       @Fetch(FetchMode.SELECT)   
       private Item item;  
    
       // ...
    }
    

    【讨论】:

      猜你喜欢
      • 2019-04-23
      • 2021-07-14
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多