Я застрял на неделю с проблемой постоянства ManyToMany с дополнительными полями. Я использую JPA и Hibernate 5.2.17.Final в качестве провайдера, Spring boot 2.0.5.RELEASE.
Это моя сущность:
@Entity
@Table(name = "personne",
uniqueConstraints = {
@UniqueConstraint(name = "nom_prenom_dateNaissance", columnNames = {"nom", "prenom", "date_naissance"})
})
@Data
@XmlRootElement
@NoArgsConstructor
public class PersonneEntity
implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@NotNull(message = "Le nom de la personne ne peut etre null")
@Column(nullable = false, length = 30)
private String nom;
@NotNull(message = "Le prenom de la personne ne peut etre null")
@Column(nullable = false, length = 30)
private String prenom;
@NotNull(message = "Le sexe de la personne ne peut etre null")
@Column(nullable = false, length = 1)
private String sexe;
@Column(length = 30)
private String profession;
@NotNull(message = "La ville de naissance de la personne ne peut etre null")
@Column(name = "ville_naissance", nullable = false, length = 30)
private String villeNaissance;
@Column(name = "date_naissance")
//@Past
private Date dateNaissance;
@OneToMany(mappedBy = "personne",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY)
@Valid
private Set<LienParenteEntity> parents = new HashSet<>();
// @OneToMany(mappedBy = "parent")
// @Valid
// private Set<LienParenteEntity> personnes = new HashSet<>();
/**
* add parente between Person and parent
* @param parente
* @param parent
*/
public void addParente(String parente, PersonneEntity parent) {
LienParenteEntity lienParenteEntity;
lienParenteEntity = new LienParenteEntity(parente, this, parent);
this.parents.add(lienParenteEntity);
//parent.getPersonnes().add(lienParenteEntity);
}
/**
* delete parente between Person and Parent
* @param parente
* @param parent
*/
public void deleteParente(String parente, PersonneEntity parent) {
for(LienParenteEntity lienParenteEntity : this.parents) {
if(StringUtils.equals(lienParenteEntity.getParente(), parente)){
if(lienParenteEntity.getParent().equals(parent)){
lienParenteEntity.setPersonne(null);
this.parents.remove(lienParenteEntity);
break;
}
}
}//for
}
}
А это моя присоединяемая таблица с дополнительным полем
@Entity
@Table(name = "lien_parente")
@Data
@ToString(exclude = {"personne", "parent"})
@EqualsAndHashCode(exclude = {"personne", "parent"})
@XmlRootElement
@NoArgsConstructor
@RequiredArgsConstructor
public class LienParenteEntity
implements Serializable
{
// @EmbeddedId
// private LienParenteId id = new LienParenteId();
@Column(nullable = false, length = 30)
@NotNull(message = "La parente ne peut etre null")
@NonNull
private String parente;
@Id
@ManyToOne
@JoinColumn(name = "personne_id")
@NonNull
private PersonneEntity personne;
@Id
@ManyToOne
@JoinColumn(name = "parent_id")
@NonNull
private PersonneEntity parent;
}
Это моя постоянная функция в классе обслуживания:
@Override
@Transactional( readOnly = false,
propagation = Propagation.REQUIRED,
rollbackFor = Exception.class)
public void insert(PersonneDto dto) {
String parente;
List<PersonneDto> parentDtos;
PersonneEntity personneEntity;
PersonneEntity parentEntity;
personneEntity = this.personMapper.asEntity(dto);
for(Iterator<String> it = dto.getParents().keySet().iterator(); it.hasNext();) {
parente = it.next();
parentDtos = dto.getParents().get(parente);
//First -> persist Parent into DB
//Second -> add Parent persisted in Personne
//Third -> persist Personn so persist LienParenty cause Cascade
for(PersonneDto parentDot : parentDtos) {
parentEntity = this.personMapper.asEntity(parentDot);
this.personneDao.save(parentEntity);
personneEntity.addParente(parente, parentEntity);
log.debug("{}", parentEntity.toString());
}//for
}//for
this.personneDao.save(personneEntity);
log.debug("{}", personneEntity.toString());
}
Я протестировал свой сервис, используя Junit с DBunit
@Test
@ExpectedDatabase(assertionMode = DatabaseAssertionMode.NON_STRICT, value = "/dataset/personne/expectedPersonne.xml")
@ExpectedDatabase(assertionMode = DatabaseAssertionMode.NON_STRICT, value = "/dataset/personne/expectedLien_parente.xml")
public void testInsert(){
...
this.service.insert(personne);
}
Я увидел, что спящий режим корректно сохраняется в обоих PersonneEntity в Table Personne, как указано в следующем журнале:
[DEBUG] org.hibernate.SQL.logStatement - insert into personne (date_naissance, nom, prenom, profession, sexe, ville_naissance) values (?, ?, ?, ?, ?, ?)
...
[DEBUG] org.hibernate.SQL.logStatement - insert into personne (date_naissance, nom, prenom, profession, sexe, ville_naissance) values (?, ?, ?, ?, ?, ?)
Но объединяемая таблица LienParenteEntity не сохраняется.
Не могли бы вы помочь мне, пожалуйста.
Thx