2016-04-21 13 views
0

Хорошо, я сейчас немного отступил. Я прочитал многие другие связанные вопросы, но это еще не помогло мне решить мою проблему. Буду рад, если кто-нибудь сможет мне помочь.Правильно каскадируйте это отношение @OneToMany (Spring Data JPA)

Я использую 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; 

Expectation

Я только экономия Readings и ожидать устройства быть каскадно правильно (сохраняется или объединены), в зависимости от того, существует ли он. (Показания только вставлены один раз, они никогда не обновляются)

Reality

Я могу только сделать эту работу частично:

Когда я использую cascade = CascadeType.ALL или cascade = CascadeType.PERSIST я могу сохранить первый Чтение и его отображаемое устройство. После того как я ввожу второе чтение, которое имеет отношение к одному устройству, я получаю что-то вдоль линий:

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

Как я понимаю, второе чтение объект пытается каскад своего устройства, вставив новую строку вместо обновление существующего.

Я могу «обойти» это, используя вместо этого cascade = CascadeType.MERGE. Теперь устройство обновляется правильно, когда я сохраняю новое Чтение с существующим объектом устройства. BUT теперь я больше не могу каскадировать устройство, которого еще нет!

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

На основании документации я удалю cascade с поля device. Документы также содержат примеры кода для хранения Phone и Person для @OneToMany и @ManyToOne, которые вы можете попробовать.

Как вы не размещать код для сохранения части я полагаю, что вы установили устройство перед сохранением reading в

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

При сохраняющихся reading объект, device должен быть сохранен автоматически.

+0

Я удалил '' каскад'', но это не помогло. По-прежнему получение '' Column 'device_id' не может быть пустым ''. Я также добавил сохраненную часть к вопросу, поскольку это может быть важно. – sldk

+0

У вас есть первичные ключи, определенные с помощью аннотации '@ Id'? Кроме того, если вы создаете новые объекты, оставьте значения id и используйте их при обновлении (но вызовите 'saveOrUpdate' в реализации Dao вместо' save') –

+0

Да. '' @Id @GeneratedValue private int id; '' '' Чтение''. '' @Id private String id; '' '' Устройство''. – sldk