У меня есть две сущности, называемые School и Level, с отношением «многие ко многим».
@Data
@Entity
public class School {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "school_generator")
@SequenceGenerator(name="school_generator", sequenceName = "school_seq", allocationSize=1)
@Column(name = "school_id")
private Long id;
@NotBlank
private String name;
@NotBlank
private String city;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(
name = "school_level",
joinColumns = @JoinColumn(name = "school_id"),
inverseJoinColumns = @JoinColumn(name = "level_id"))
private Set<Level> levels = new HashSet<>();
}
@Data
@Entity
public class Level implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "level_generator")
@SequenceGenerator(name = "level_generator", sequenceName = "level_seq", allocationSize = 1)
@Column(name = "level_id")
private Long id;
@NotBlank
@Column(nullable = false, unique = true)
private String name;
}
My SchoolController
, контроллер Rest, имеет метод create, который принимает SchoolDTO (сейчас это имеет ту же структуру, что и объект).
Когда я публикую DTO, уровни вложенного дочернего списка заполняются только существующими идентификаторами уровней (так как уровни создаются ранее).
Когда я пытаюсь сохранить с помощью метода сохранения JPARepository ... Выдается исключение с этим сообщением:
"detached entity passed to persist: com.salimrahmani.adawat.domain.Level; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.salimrahmani.adawat.domain.Level",
"trace": "org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist:
Проблема решается путем итерации каждого идентификатора уровня ... получить ссылки с помощью метода репозитория JPA getOne
(который вызывает entityManager.getReference
), а затем загружает правильную модель и затем успешно сохраняется.
@PostMapping("/{id}/grades")
public ResponseEntity<SchoolDTO> addLevelToPackage(@PathVariable Long id, @RequestBody @Valid LevelDTO levelDTO) {
return schoolService.findById(id)
.map(school -> {
Level level = levelMapper.map(levelDTO);
if(level.getId() != null) {
level = levelService.getOne(level.getId());
school.getLevels().add(level);
} // else error
School saved = schoolService.save(school);
return ResponseEntity.ok(schoolMapper.map(saved));
}).orElseGet(() -> ResponseEntity.notFound().build());
}
Мой вопрос: это "единственный" правильный способ публикации ассоциации в Spring Data? Или есть способ получше?