jpa - 单向多对一:保存父实体会在子表中生成不需要的插入
问题描述
我需要使用@JoinColumn @ManyToOne 列作为复合主键的一部分(具有定义复合键@IdClass 的首选选项,而不是@EmbeddedId)。
所涉及的实体是父子关系 - 类似于员工和部门的关系,唯一的区别是我只需要从父(“员工”)访问子(“部门”)字段,反之亦然。因此,我在父实体中使用单向 @ManyToOne。
目前我在更新父表时遇到问题 - 在父实体更新时,hibernate 尝试将记录插入到子表中,并且可以理解地因主键违规而失败。我需要抑制对子表的插入。我希望注释中的 'insertable = false, updatable = false' 可以解决问题,但事实并非如此。
我使用这些指南来设置复合主键:https://www.baeldung.com/jpa-composite-primary-keys,https://dwuysan.wordpress.com/2012/02/22/joincolumn-is- part-of-the-composite-primary-keys/ , https://vladmihalcea.com/the-best-way-to-map-a-composite-primary-key-with-jpa-and-hibernate/
我的代码如下。父实体:
@Data
@Builder
@Entity
@Table(name = "Parent", schema = "dbo")
@IdClass(value = ParentPrimaryKey.class)
public class Parent {
@Id
@Column(name = "dateTime", insertable = false, updatable = false)
private Timestamp dateTime;
@Id
@MapsId("child")
@ManyToOne
@JoinColumn(name = "child", insertable = false, updatable = false)
private Child child;
@Column(name = "status")
private Integer status;
}
父母的主键实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ParentPrimaryKey implements Serializable {
private static final long serialVersionUID = 1;
private Timestamp dateTime;
private String child;
}
子实体:
@Data
@Entity(name = "Child")
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Child", schema = "dbo")
public class Location implements Serializable {
private static final long serialVersionUID = 1;
@Id
@Column(name = "child")
private String child;
@Column(name = "param")
private String param;
// some other child param fields
}
在内存 H2 上进行集成测试,提供 TestTable 的一些条目:
@Test
public void shouldSaveRecord() {
Parent selectedRecord = parentRepository.findAll().get(0);
selectedRecord.setStatus(9);
parentRepository.save(selectedRecord);
}
运行测试产生的日志:
2019-07-01 09:52:20.547 [main] DEBUG org.hibernate.SQL - select parent0_.dateTime as dateTime1_15_, parent0_.child as child 3_15_, parent0_.status as status4_15_ from dbo.Parent parent0_
2019-07-01 09:52:20.555 [main] DEBUG org.hibernate.SQL - select child0_.child as child1_5_0_, child0_.param as param3_5_0_ from dbo.Child child0_ where child0_.child=?
2019-07-01 09:52:20.602 [main] DEBUG org.hibernate.SQL - select parent0_.dateTime as dateTime1_15_0_, parent0_.child as child3_15_0_, parent0_.status as status4_15_0_ from dbo.Parent parent0_ where parent0_.dateTime=? and parent0_.child=?
2019-07-01 09:52:20.630 [main] DEBUG org.hibernate.SQL - insert into dbo.child (child, param) values (?, ?)
2019-07-01 09:52:20.636 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 23505, SQLState: 23505
2019-07-01 09:52:20.636 [main] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Unique index or primary key violation: "PRIMARY_KEY_81 ON DBO.CHILD(CHILD) VALUES ('MTS_0102_010R4', 8)"; SQL statement:
insert into dbo.child (child, param) values (?, ?) [23505-197]
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PRIMARY_KEY_81 ON DBO.CHILD(CHILD) VALUES ('MTS_0102_010R4', 8)"; SQL statement:
insert into dbo.child (child, param) values (?, ?) [23505-197]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
我需要抑制不需要的插入到子表中。任何帮助将不胜感激。
更新于 2019 年 7 月 2 日。当前解决方案:必须切换到@EmbeddedId。有点痛苦,因为我必须更新所有非本地查询。仍然想知道它是否可以使用@IdClass 进行管理。
解决方案
推荐阅读
- sql - 将 wkt 转换为 oracle 几何
- java - Kafka 主题不断添加到 DLT 主题中
- python - 尽管存在对象,但“NoneType”对象没有属性“seventh_five”
- javascript - 如何压缩 ObjectID 以使其更短
- r - 修改递归的 discogs 列表
- python - 升级到 Chromedriver 76 导致警报自动关闭
- python - 逐行计算熊猫数据帧
- c# - SSIS 包在我的机器上执行良好,但作为 SQL 作业失败
- python - 如何修复' raise ValueError("unknown url type: %r" % self.full_url) ValueError: unknown url type: '''
- python - .txt 文件中的列表不会转换为列表