2016-04-21 48 views
0

好的,我现在有点纠结了。我读过很多其他相关问题,但这并没有帮助我解决我的问题。如果有人能帮助我,我会很高兴。正确地级联这个@OneToMany关系(Spring数据JPA)

我使用Spring数据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来“解决”这个问题。现在,当我使用现有的Device实体保存新的Reading时,该设备会正确更新。 但是现在我不能再级联一个还不存在的设备!

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); 

我想这个问题的一部分,可能与我做设置分离实体?

我在做什么错?我的身份不好吗?发生什么事?我是否需要手动管理这些交易?

谢谢!

回答

0

根据定义,@OneToMany关联是父关联,即使是单向关联或双向关联。只有组织的父方才有意义将其实体状态转换为儿童。 (来源:Hibernate docs)。

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

当你没有张贴保存一部分,我想任何代码,保存之前设置设备reading作为

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

当坚持reading对象device应被自动保存。

+0

我删除了''cascade''但没有帮助。仍然获得''列'device_id'不能为空''。我也为这个问题增加了保存部分,因为它可能很重要。 – sldk

+0

您是否使用'@ Id'注释定义了主键?此外,如果您正在创建新对象,则保留id值并在更新时使用它们(但在Dao实现中调用'saveOrUpdate'而不是'save') –

+0

是的。 ''@Id @GeneratedValue private int id;''''阅读''。 ''@私有字符串ID;''在''设备''上。 – sldk