Mam ęncję w relacji 1 do wielu z inną encją (dwukierunkowa relacja). Po stronie jeden (jest lista obiektów dziecka) a po stronie wiele jest obiekt rodzica. Jak tworzę obiekt rodzica lub chcę go zapisać po modyfikacji, to zapisuje/aktualizuje mi się obiekt rodzic (np. pole name), ale nie zapisuje się pole z listą dzieci. W debbugerze pokazuje, że obiekt rodzic trzyma poprawną listę dzieci, ale przy save do repo rodzica, nic się nie zmienia oprócz podstawowych pól rodzica.

Spring + Hibernate

Encja rodzica:

@Entity(name = "trainings")
public class TrainingEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotEmpty
    @Column(nullable = false, length = 60)
    private String name;
    @OneToMany(mappedBy = "training", cascade = CascadeType.ALL)
    private Set<BlockEntity> blocks;
    @OneToMany(mappedBy = "training", cascade = CascadeType.ALL)
    private Set<TrainingApplicationEntity> applications = new HashSet<>();

Encja dziecka:

@Entity(name = "blocks")
public class BlockEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotEmpty
    @Column(nullable = false, length = 60)
    private String name;
    @ManyToOne
    private TrainingEntity training;
    @OneToMany
    @JoinColumn(name = "classes")
    private Set<ClassesEntity> classes = new HashSet<>();

DTO rodzica:

public class TrainingDTO {
    private Long id;
    private String name;
    private Set<BlockEntity> blocks;
    private List<Long> blockIds;
    private List<Long> applicationIds;

DTO dziecka:

public class BlockDTO {
    private Long id;
    private String name;
    private TrainingEntity training;
    private Set<ClassesEntity> classes;

Serwis rodzica:

  public void createTraining(TrainingDTO trainingDTO) {
       TrainingEntity newtrainingEntity = trainingMapper.toEntity(trainingDTO);
       trainingRepository.save(newtrainingEntity);
       LOGGER.info("Dodano nowy kurs: " + newtrainingEntity.getName());
   }
   public void updateTraining(Long id, TrainingDTO trainingDTO) {
       TrainingEntity trainingEntity = trainingMapper.toEntity(trainingDTO);
       trainingRepository.saveAndFlush(trainingEntity.setId(id));
       LOGGER.info("Pomyślnie zaktualizowano kurs: " + trainingEntity.getName());
   }

Kontroler:

    @GetMapping("/addtraining")
    public String getTrainingToCreate(Model model) {
        model.addAttribute("trainingDto", new TrainingDTO());
        final List<BlockDTO> allBlocks = blockService.getAllBlocks();
        model.addAttribute("allBlocks", allBlocks);
        return "addtraining";
    }
    @PostMapping("/addtraining")
    public String postTrainingToCreate(Model model, TrainingDTO trainingDTO) {
        trainingService.createTraining(trainingDTO);
        return "redirect:/trainings";
    }
    @GetMapping("/training/edit/{id}")
    public String getTrainingToEdit(@PathVariable Long id, Model model) {
        final TrainingDTO trainingDTO = trainingService.getTrainingById(id);
        model.addAttribute("trainingDto", trainingDTO);
        final List<BlockDTO> allBlocks = blockService.getAllBlocks();
        model.addAttribute("allBlocksDto", allBlocks);
        return "training";
    }
    @PostMapping("/training/update/{id}")
    public String postTrainingToUpdate(@PathVariable Long id, TrainingDTO trainingDTO) {
        trainingService.updateTraining(id, trainingDTO);
        return "redirect:/trainings";
    }

Z szablonu Thymeleafa wychodzi DTO rodzica z listą ID, która jest mapowana na encję.

W debbugerze, tuż przed zapisem encji do bazy, encja posiada utworzoną / zaktualizowaną listę dzieci. Po zapisie do repo aktualizuje się rodzic, bez pola relacji z dzieckiem.