I load and entity A qui a one to many on a list of entities B. This is passed to m UI where in can add / remove / modify the list of entities B. Then I post back those entities modifications are not set in database after the transation. I would like to understand why and what I must do to achieve this (The only back solution I found is to remove all data and recreate ; I do not consider this as a reel solution).
Here are my entities :
Entity A
@Entity
@Table(name = "GL_RENTAL")
public class GlRental implements Serializable {
private static final long serialVersionUID = 3721662952504926000L;
@Id
@Column(name = "PK_RENTAL")
@GeneratedValue(generator = "TableGenerator")
@GenericGenerator(name = "TableGenerator", strategy = "com......TableGenerator", parameters = { @Parameter(name = "segment_value", value = "GL_RENTAL") })
private Integer pk;
@Version
@Column(name = "DATE_VERSION")
private Date version;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "PK_UT")
QuantificationRD quantification;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "PK_RENTAL", nullable = false)
@OrderColumn(name = "INDEX_ORDER")
private List<GlRentalPeriod> periods = new ArrayList<>();
...
Entity B
@Entity
@Table(name = "GL_RENTAL_PERIOD")
public class GlRentalPeriod implements Serializable {
private static final long serialVersionUID = -8190230568391952427L;
@Id
@Column(name = "PK_RENTAL_PERIOD")
@GeneratedValue(generator = "TableGenerator")
@GenericGenerator(name = "TableGenerator", strategy = "com......TableGenerator", parameters = { @Parameter(name = "segment_value", value = "GL_RENTAL_PERIOD") })
private Integer pk;
@Version
@Column(name = "DATE_VERSION")
private Date version;
@Column(name = "TYPE")
private String type;
@Column(name = "AMOUNT")
private Double amount;
@Column(name = "DATE_START")
private Date dateStart;
@Column(name = "DATE_END")
private Date dateEnd;
@Column(name = "FRANCHISE")
private Double franchise;
@Column(name = "FRANCHISE_TYPE")
private String franchiseType;
@Column(name = "FRANCHISE_UNIT")
private String franchiseUnit;
@Column(name = "PAID")
private Boolean paid;
....
Here is the service
@Service
@Transactional
public class GlUtServiceImpl implements GlUtService {
@Autowired
ProduitService produitService;
@Autowired
ContractService contractService;
@Autowired
UtDao utDao;
@Autowired
GlUtDao glUtDao;
...
@Override
public void updateRental(ContexteService contexte, Integer pkUT, GlRentalBo rentalBo) {
UniteTraitement uniteTraitement = utDao.rechercherUT(pkUT);
QualificationUT qualif = uniteTraitement.getQualification();
Declaration declaration = qualif.getDeclaration();
Gestionnaire gestionnaire = gestionnaireDao.rechercherGestionnaire(contexte.getIdentifiantUtilisateur());
verificationHabilitationService.verifierDroitTraitement(gestionnaire, uniteTraitement);
verificationHabilitationService.verifierOuvertureUT(uniteTraitement);
GlRental rentalDto = rentalBo.getRental();
if (rentalDto.getPk() == null) {
// Attach qualification with rental
UtDao utDao = (UtDao) glUtDao;
QuantificationRD quantif = utDao.rechercherQuantificationRD(pkUT);
if (quantif == null) {
throw new ExceptionPkEntiteInconnu(UT.class, pkUT);
}
if (rentalDto.getQuantification() != null) {
throw new ExceptionConcurrenceOptimiste("Des informations de loyer existent déjà");
}
rentalDto.setQuantification(quantif);
// Save
glUtDao.createRental(rentalDto);
}
else {
GlRental rental = glUtDao.getRental(pkUt)); // error is here, this is readonly request
List<GlRentalPeriod> rentalPeriodRemovals = new ArrayList<>();
for (GlRentalPeriod rentalPeriod : rental.getPeriods()) {
GlRentalPeriod rentalPeriodToRemove = rentalPeriod;
for (GlRentalPeriod rentalPeriodDto : rentalDto.getPeriods()) {
// Period already exists in database : modify date
if (rentalPeriodDto.getPk() != null && Integer.compare(rentalPeriodDto.getPk(), rentalPeriod.getPk()) == 0) {
rentalPeriodToRemove = null;
rentalPeriod.setAmount(rentalPeriodDto.getAmount());
rentalPeriod.setDateStart(rentalPeriodDto.getDateStart());
rentalPeriod.setDateEnd(rentalPeriodDto.getDateEnd());
rentalPeriod.setFranchise(rentalPeriodDto.getFranchise());
rentalPeriod.setFranchiseType(rentalPeriodDto.getFranchiseType());
rentalPeriod.setFranchiseUnit(rentalPeriodDto.getFranchiseUnit());
rentalPeriod.setPaid(rentalPeriodDto.getPaid());
rentalPeriod.setType(rentalPeriodDto.getType());
break;
}
}
// Period not found, to remove, set it in a list of periods to remove from database
if (rentalPeriodToRemove != null) {
rentalPeriodRemovals.add(rentalPeriod);
}
}
if (CollectionUtils.isNotEmpty(rentalPeriodRemovals)) {
rental.getPeriods().removeAll(rentalPeriodRemovals);
}
// Additionnal periods
List<GlRentalPeriod> rentalPeriodAdditionnals = rentalDto.getPeriods().stream().filter(period -> period.getPk() == null)
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(rentalPeriodAdditionnals)) {
rental.getPeriods().addAll(rentalPeriodAdditionnals);
}
glUtDao.updateRental(rental);
}
}
}