2 votes

Sauvegarde (mise à jour) du référentiel de données de Spring Jpa avec LinkedEntity pour la relation ManyToMany

Il y a 2 entités (disons Règle et Étiquette) avec une relation many-to-many utilisant une entité liée. selon la documentation de référence d'Hibernate
Règle enity :

@Entity
@Table(name = "rule")
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "name")
public class Rule implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NaturalId
@NotBlank
@Column(unique = true)
private String name;

@Lob
@Column(columnDefinition = "TEXT")
private String content;

@OneToMany(mappedBy = "rule", cascade = {CascadeType.PERSIST, 
    CascadeType.MERGE})
private List<RuleLabel> labels = new ArrayList<>();
...

Entité d'étiquetage :

@Entity
@Table(name = "label")
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id")
public class Label implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank
private String name;

@OneToMany(mappedBy = "label", cascade = {CascadeType.PERSIST, 
    CascadeType.MERGE})
private List<RuleLabel> rules = new ArrayList<>();
...

Entité de liaison :

@Entity
public class RuleLabel implements Serializable {

@Id
@ManyToOne
private Rule rule;

@Id
@ManyToOne
private Label label;
...

Dépôts :

@Repository
public interface LabelRepository extends JpaRepository<Label, Long>
...
@Repository
public interface RuleRepository extends JpaRepository<Rule, Long>
...

Création d'une nouvelle entité via RuleRepository.save(Rule) fonctionne bien, mais lorsque j'essaie de mettre à jour une entité existante (la même méthode RuleRepository.save(Rule) mais l'entité à sauver contient id ), cela conduit à une boucle infinie de Hibernate : select... des requêtes :

Hibernate: select rule0_.id as id1_7_1_, rule0_.is_active as is_activ2_7_1_, rule0_.content as content3_7_1_, rule0_.is_deleted as is_delet4_7_1_, rule0_.import_section as import_s5_7_1_, rule0_.name as name6_7_1_, rule0_.rule_configuration as rule_con7_7_1_, labels1_.rule_id as rule_id1_8_3_, labels1_.label_id as label_id2_8_3_, labels1_.rule_id as rule_id1_8_0_, labels1_.label_id as label_id2_8_0_ from rule rule0_ left outer join rule_label labels1_ on rule0_.id=labels1_.rule_id where rule0_.id=?

et StackOverflowError en conséquence

java.lang.StackOverflowError: null
at com.mysql.jdbc.ServerPreparedStatement.getInstance(ServerPreparedStatement.java:332)
...

(LabelRepository agit de la même manière)
Comment le réparer ?
Mise à jour : Après avoir changé la stratégie de récupération en Lazy

@Id
@ManyToOne(fetch = FetchType.LAZY)
private Rule rule;

@Id
@ManyToOne(fetch = FetchType.LAZY)
private Label label;

le problème de la boucle infinie a disparu, mais un nouveau problème est apparu - les entités liées ne sont pas alimentées et lorsque Hibernate essaie d'insérer des valeurs dans la table de liens

Hibernate: insert into rule_label (rule_id, label_id) values (?, ?)

on obtient

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'rule_id' cannot be null

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X