正确地级联@OneToMany关系(Spring Data JPA)

时间:2016-04-21 19:48:42

标签: hibernate jpa spring-data-jpa cascade many-to-one

好吧,我现在有点乖乖。我已经阅读了许多其他相关问题,但这并没有帮助我解决我的问题。如果有人可以帮助我,我会很高兴。

我正在使用Spring Data JPA,我有这两个实体:

Device.class

private String id;

@OneToMany(mappedBy = "device", cascade = CascadeType.ALL)
@JsonIgnore
@RestResource(exported = false)
private List<Reading> readings;

Reading.class

@ManyToOne(cascade = {CascadeType.MERGE}) /*This isn't right...*/
@JoinColumn(name = "device_id")
private Device device;

期望

我只保存读数,并希望设备能够正确级联(持久或合并),具体取决于它是否已存在。 (读数只插入一次,永远不会更新)

现实

我只能将此作品部分

当我使用cascade = CascadeType.ALLcascade = CascadeType.PERSIST时,我可以保存首先阅读及其映射的设备。一旦我插入了与同一设备有关系的第二个阅读,我就会得到以下内容:

Duplicate entry '457129' for key 'PRIMARY'
('457129' = Reading.Device.id)

据我所知,第二个读取实体尝试通过插入新行而不是更新现有行来级联其设备。

我可以使用cascade = CascadeType.MERGE代替“解决”这个问题。现在,当我使用现有设备实体保存新读数时,设备会正确更新。 但是现在我再也无法级联一个尚不存在的设备了!

Column 'device_id' cannot be null 
(Reading.device_id)

保存

我收到JSON DTO并从中创建实体。

伪代码:

Reading reading = deserialize(jsonReading);
Device device = deserialize(device);

reading.setDevice(device); /* Device entity is detached */

readingService.save(reading);

我想部分问题可能与我设置一个分离的实体有关?

我做错了什么?我的关系不好吗?怎么了?我是否需要手动管理这些交易?

谢谢!

1 个答案:

答案 0 :(得分:0)

  

@OneToMany关联定义为父关联,即使它是单向关联或双向关联。只有关联的父方才有意义将其实体状态转换级联到子级。 (来源:Hibernate docs)。

根据文档,我将从cascade字段中删除device。文档还包含用于存储您可能尝试的PhonePerson的{​​{1}}和@OneToMany的代码示例。

由于您没有发布任何用于保存部分的代码,我认为您在将@ManyToOne保存为

之前设置了设备
reading

持久存储reading.setDevice(device); readingDao.save(reading); // depends on your implementation 对象后,reading应自动保存。