es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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?

Tags:  , ,

Answer

  1. Avatar for 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 objeto Utilisateur y añadiéndolo a la lista delegates, se fusionará con el objeto Utilisateur 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í:

    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "entity_delegate",
            joinColumns = @JoinColumn(name = "entity_id"),
            inverseJoinColumns = @JoinColumn(name = "utilisateur_id"))
    private List<utilisateur> delegates = new ArrayList<>();
    

    O puedes eliminar por completo el tipo de cascada:

    @ManyToMany
    @JoinTable(name = "entity_delegate",
            joinColumns = @JoinColumn(name = "entity_id"),
            inverseJoinColumns = @JoinColumn(name = "utilisateur_id"))
    private List<utilisateur> delegates = new ArrayList<>();
    

    De cualquier manera, se asegurará de que no se cree una nueva fila en la base de datos cuando ya exista una entidad secundaria.

Comments are closed.