sql >> Base de Datos >  >> RDS >> Mysql

JPA inserta resultados padre/hijo en MySQLIntegrityConstraintViolationException

Su relación no tiene que ser bidireccional. Hay información errónea en los comentarios aquí.

También dijo que había agregado el campo "parentId" en la entidad secundaria porque asumió que JPA necesita "saber" sobre el campo principal para que pueda establecer el valor. El problema no es que JPA no conozca el campo, según las anotaciones que ha proporcionado. El problema es que proporcionó "demasiada" información sobre el campo, pero esa información no es coherente internamente.

Cambie su campo y anotación en Padre a:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id")
private List<Child> children;

Luego, elimine el "parentId" de la entidad secundaria por completo. Previamente había especificado una anotación JoinTable. Sin embargo, lo que quieres no es una JoinTable. Un JoinTable crearía una tercera tabla adicional para relacionar las dos entidades entre sí. Lo que quieres es solo un JoinColumn. Una vez que agregue la anotación JoinColumn en un campo que también está anotado con OneToMany, su implementación de JPA sabrá que está agregando un FK en la tabla CHILD. El problema es que JPA tiene una tabla CHILD ya definida con una columna parent_id.

Piense en ello que le está dando dos definiciones contradictorias tanto de la función de la tabla CHILD como de la columna parent_id. En un caso, le ha dicho a JPA que es una entidad y parent_id es simplemente un valor en esa entidad. En el otro, le ha dicho a JPA que su tabla CHILD no es una entidad, pero se usa para crear una relación de clave externa entre su tabla CHILD y PARENT. El problema es que su tabla CHILD ya existe. Luego, cuando persiste su entidad, le ha dicho que parent_id es explícitamente nulo (no establecido), pero también le ha dicho que su parent_id debe actualizarse para establecer una referencia de clave externa a la tabla principal.

Modifiqué su código con los cambios que describí anteriormente y también llamé a "persistir" en lugar de "fusionar".

Esto resultó en 3 consultas SQL

insert into PARENT (ID) values (default)
insert into CHILD (ID) values (default)
update CHILD set parent_id=? where ID=?

Esto refleja lo que quieres perfectamente. Se crea la entrada PADRE. Se crea la entrada CHILD y luego se actualiza el registro CHILD para establecer correctamente la clave externa.

Si, en cambio, agrega la anotación

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id", nullable = false)
private List<Child> children;

Luego ejecutará la siguiente consulta cuando inserte al niño

insert into CHILD (ID, parent_id) values (default, ?)

configurando así su FK correctamente desde el principio.