Итак, у меня есть такой сценарий, когда мне нужно взять запись заголовка, удалить данные для него, а затем повторно создать детали по-другому. Обновление деталей было бы слишком сложной задачей.Удалить, затем создать записи, вызывает дублирующее нарушение ключа с помощью Spring Data JPA
я в основном имеют:
@Transactional
public void create(Integer id, List<Integer> customerIDs) {
Header header = headerService.findOne(id);
// header is found, has multiple details
// Remove the details
for(Detail detail : header.getDetails()) {
header.getDetails().remove(detail);
}
// Iterate through list of ID's and create Detail with other objects
for(Integer id : customerIDs) {
Customer customer = customerService.findOne(id);
Detail detail = new Detail();
detail.setCustomer(customer);
header.getDetails().add(detail);
}
headerService.save(header);
}
Теперь база данных имеет ограничение вроде следующего:
Header
=================================
ID, other columns...
Detail
=================================
ID, HEADER_ID, CUSTOMER_ID
Customer
=================================
ID, other columns...
Constraint: Details must be unique by HEADER_ID and CUSTOMER_ID so:
Detail (VALID)
=================================
1, 123, 10
2, 123, 12
Detail (IN-VALID)
=================================
1, 123, 10
1, 123, 10
OK, когда я запускаю это и передать в 2, 3, 20 и т.д. клиентов, он создает все записи Detail
просто отлично, пока их не было.
Если я запустил его снова, перейдя в другой список клиентов, я ожидаю, что детали ALL
будут удалены сначала, а затем список из NEW
. Подробности будут созданы.
Но все, что происходит, заключается в том, что удаление не выполняется перед созданием. Поскольку ошибка является дублирующим ключевым ограничением. Дублирующий ключ - это сценарий «IN-VALID» выше.
Если я вручную заполняю базу данных кучей деталей и комментирую часть CREATE details
(только запустите удаление), тогда записи удаляются просто отлично. Таким образом, удаление работает. Создает работы. Просто они не работают вместе.
Я могу предоставить больше кода. Я использую Spring Data JPA
.
Благодаря
UPDATE
Мои объекты помечаются в основном следующие:
@Entity
@Table
public class Header {
...
@OneToMany(mappedBy = "header", orphanRemoval = true, cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
private Set<Detail> Details = new HashSet<>();
...
}
@Entity
@Table
public class Detail {
...
@ManyToOne(optional = false)
@JoinColumn(name = "HEADER_ID", referencedColumnName = "ID", nullable = false)
private Header header;
...
}
UPDATE 2
@Klaus Groenbaek
На самом деле, я не упоминал об этом изначально, но я сделал это в первый раз. Кроме того, я использую Cascading.ALL, который, как я предполагаю, включает PERSIST.
Только для тестирования, я обновил свой код к следующему:
@Transactional
public void create(Integer id, List<Integer> customerIDs) {
Header header = headerService.findOne(id);
// Remove the details
detailRepository.delete(header.getDetails()); // Does not work
// I've also tried this:
for(Detail detail : header.getDetails()) {
detailRepository.delete(detail);
}
// Iterate through list of ID's and create Detail with other objects
for(Integer id : customerIDs) {
Customer customer = customerService.findOne(id);
Detail detail = new Detail();
detail.setCustomer(customer);
detail.setHeader(header);
detailRepository.save(detail)
}
}
Опять ... Я хочу повторить .... что удаление будет работать, если у меня нет непосредственно создать после этого. Создать WILL WORK, если у меня нет удаления непосредственно перед ним. Но ни одна из них не будет работать, если они объединены из-за ошибки дублирования ключевого ограничения из базы данных.
Я пробовал один и тот же сценарий WITH и без каскадных удалений.
Это зависит от того, как вы отображали детали ... просто '.remove (...)' они не всегда удаляют строки в БД – Andremoniy
Итак, вы должны предоставить свои сущности аннотации – Andremoniy
Не знаете, почему я ' м получить близкие голоса? В любом случае ... @Andremoniy да, я аннотировал мои сущности с Cascade все. Я обновлю эту информацию. – cbmeeks