【问题标题】:Properly cascading this @OneToMany relationship (Spring Data JPA)正确级联此@OneToMany 关系(Spring Data JPA)
【发布时间】:2016-04-21 19:48:42
【问题描述】:

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

我正在使用 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;

期待

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

现实

我只能部分完成这项工作

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

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

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

我可以改用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);

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

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

谢谢!

【问题讨论】:

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


    【解决方案1】:

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

    根据文档,我将从device 字段中删除cascade。 Docs 还包含用于存储 @OneToMany@ManyToOnePhonePerson 的代码示例,您可以尝试。

    由于您没有发布任何保存部分的代码,我想您在将reading 保存为之前设置了设备

    reading.setDevice(device);
    readingDao.save(reading); // depends on your implementation
    

    当持久化reading 对象时,device 应该被自动保存。

    【讨论】:

    • 我删除了cascade,但这并没有帮助。仍然收到Column 'device_id' cannot be null 。我还在问题中添加了保存部分,因为它可能很重要。
    • 您是否有使用@Id 注释定义的主键?此外,如果您正在创建新对象,请保留 id 值并在更新时使用它们(但在 Dao 实现中调用 saveOrUpdate 而不是 save
    • 是的。 @Id @GeneratedValue private int id;Reading@Id private String id; Device
    • 尝试将设备ID字段更改为与阅读时相同。重复条目表示您正在尝试插入一个已经存在的设备。如果您需要一个设备用于更多读数,您应该使用多对多关系。
    猜你喜欢
    • 2021-02-10
    • 1970-01-01
    • 2019-10-25
    • 2019-05-17
    • 2014-11-16
    • 1970-01-01
    • 2021-12-27
    • 2019-04-26
    • 1970-01-01
    相关资源
    最近更新 更多