Fila duplicada en la base de datos creada con la asociación ManyToMany y cascadeType. MERGE
Trabajo con JPA, Hibernate y Spring Boot.
Tengo un problema con JPA: cuando guardo una entidad que tiene una asociación ManyToMany con la propiedad CascadeType.MERGE, la entidad secundaria se crea aunque ya exista en la tabla de la base de datos.
Tengo la siguiente entidad.
@Entity
@Table(name = "ENTITY")
@NoArgsConstructor
@AllArgsConstructor
public class EntityList implements Serializable {
...
@ManyToMany(cascade=CascadeType.MERGE)
@JoinTable( name = "entity_delegate",
joinColumns = @JoinColumn(name = "entity_id"),
inverseJoinColumns = @JoinColumn(name = "utilisateur_id") )
private List<utilisateur> delegates = new ArrayList<>();
...
}
La entidad Utilisateur es la siguiente.
@Entity
@Table(name = "UTILISATEUR")
@NoArgsConstructor
@AllArgsConstructor
public class Utilisateur implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull
private Integer id;
private String firstname;
private String lastname;
private String accountAD;
private String fonction;
...
}
En la base de datos, ya existen los siguientes Utilisateur.
id firstname lastname accountad fonction
44 "StaffAccess02" "FINS" "StaffAccess02" null
Cuando aplico el siguiente código.
EntityList entity = entityListList.get(0);
List<utilisateur> delegates = new ArrayList<>();
delegates.add(new Utilisateur("StaffAccess02", "FINS", "StaffAccess02", null));
entity.setDelegates(delegates);
entity = entityListRepository.save(entity);
Se crea una segunda fila con los mismos valores en las columnas.
id firstname lastname accountad fonction
51 "StaffAccess02" "FINS" "StaffAccess02" null
¿Cómo puedo evitar esto?
davy.ai
El problema que estás enfrentando se debe a la propiedad
CascadeType.MERGE
que se está utilizando en la asociación@ManyToMany
. Este tipo de cascada fusionará el estado de la entidad secundaria con el estado de la entidad principal cuando se guarde la entidad principal. En tu caso, dado que estás creando un nuevo objetoUtilisateur
y añadiéndolo a la listadelegates
, se fusionará con el objetoUtilisateur
existente en la base de datos, lo que resultará en la inserción de una nueva fila en la tabla.Para evitar esto, puedes cambiar el tipo de cascada a
CascadeType.PERSIST
o eliminar el tipo de cascada por completo.CascadeType.PERSIST
asegurará que se cree y persista una nueva entidad secundaria en la base de datos cada vez que se guarde la entidad principal.Entonces, tu nueva asociación
@ManyToMany
se verá así:O puedes eliminar por completo el tipo de cascada:
De cualquier manera, se asegurará de que no se cree una nueva fila en la base de datos cuando ya exista una entidad secundaria.