У меня есть простое однонаправленное отношение Parent Child в моем приложении Spring Web MVC. У меня есть 2 RESTful API: POST & PUT.
Родительский субъект:
@Entity
@EqualsAndHashCode(exclude = {"children", "id"})
public class Parent {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "PARENT_ID", nullable = false, updatable = false)
private Set<Child> children = new HashSet<>();
}
Дочерняя сущность:
@Entity
@EqualsAndHashCode(exclude = {"id"})
public class Child {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String name;
}
Контроллер:
@RestController
@RequestMapping("/parent")
public class Controller {
@Autowired
private ServiceImpl serviceImpl;
@PostMapping
public ResponseEntity<Parent> post(@RequestBody final Parent parent) {
return new ResponseEntity<Parent>(serviceImpl.create(parent), HttpStatus.OK);
}
@PutMapping
public ResponseEntity<Parent> put(@RequestBody final Parent parent) {
return new ResponseEntity<Parent>(serviceImpl.update(parent), HttpStatus.OK);
}
}
Уровень обслуживания:
@Service
public class ServiceImpl implements inter {
@Autowired
ParentRepository repository;
public Parent create(Parent parent) {
return repository.save(parent);
}
@Transactional(readOnly = true)
public Parent findById(Long id) {
return repository.findById(id).orElseThrow(IllegalArgumentException::new);
}
@Transactional
public Parent update(Parent toUpdate) {
Parent retrieved = this.findById(toUpdate.getId());
retrieved.getChildren().retainAll(toUpdate.getChildren());
retrieved.getChildren().addAll(toUpdate.getChildren());
return repository.save(retrieved);
}
}
У меня есть один репозиторий для родителей.
Я создаю Родителя и детей вместе как часть API POST
Мне нужно обновить Parent и Children через PUT.
Однако, когда я пытаюсь заменить одного или нескольких дочерних элементов уже созданного Parent, я получаю сообщение об ошибке:
{"timestamp":"2019-05-27T20:21:53.451+0000","status":500,"error":"Internal Server Error","message":"Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1","path":"/parent"}
Проблема возникает только при выполнении простого тестового теста JMETER с несколькими потоками.
Если я изменяю CascadeType на MERGE на родительской стороне отношений, тогда обновление работает, но сохранение новой сущности затем не удастся через Post api.