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.

¿Por qué obtengo una java.sql.SQLIntegrityConstraintViolationException en una relación many-to-many de Hibernate (restricción de clave externa)?

Tengo una tabla llamada “tbl_books” que tiene una relación muchos a muchos con “tbl_author”. Quiero guardar un libro y sus autores. Puedo guardar el libro si no incluyo una lista de autores, pero ¿cómo debo guardar los autores al libro? ¿Necesito crear la tabla “tbl_book_authors” para lograr esto?

{
“title”: “un nuevo libro”,
“publisher”: {
“id”: 7
},
“authors”: [
{
“id”: 3
}
]
}

Imagen:

Log:

Book.java

@NoArgsConstructor
@Entity(name=”Book”)
@Table(name=”tblBook”)
public class Book {

@Id
@Column(name = "id", unique = true, nullable = false)
private int id;
private String title;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "pub_id", nullable = false)
private Publisher publisher;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "tblBookAuthors",
        joinColumns = { @JoinColumn(name = "bookId") },
        inverseJoinColumns = { @JoinColumn(name = "authorId") })
private Set<author> authors = new HashSet<>();

...

}

author.java

@NoArgsConstructor
@Entity(name=”Author”)
@Table(name=”tblAuthor”)
public class Author {

@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@JsonBackReference
@ManyToMany(mappedBy = "authors")
Set<book> books;

...

}

log

Book{id=0, title=’un nuevo libro’, publisher=Publisher{id=7, name=’null’, address=’null’, phone=’null’, books=null}, authors=[Author{id=3, name=’null’, books=null}]}
Hibernate: select publisher_.id, publisher_.address as address2_4_, publisher_.name as name3_4_, publisher_.phone as phone4_4_ from tbl_publisher publisher_ where publisher_.id=?
Hibernate: insert into tbl_book (pub_id, title, id) values (?, ?, ?)
Hibernate: insert into tbl_book_authors (book_id, author_id) values (?, ?)
2021-11-27 18:49:06.643 WARN 8704 — [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1452, SQLState: 23000
2021-11-27 18:49:06.643 ERROR 8704 — [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : No se puede agregar o actualizar una fila secundaria: falla una restricción de clave externa (library.tbl_book_autors, CONSTRAINT fk_tbl_book_authors_tbl_book1 FOREIGN KEY (book_id) REFERENCES tbl_book (id) ON DELETE CASCADE ON UPDATE CASCADE)
2021-11-27 18:49:06.644 INFO 8704 — [nio-8080-exec-7] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: En la liberación del conjunto todavía contenía declaraciones JDBC
2021-11-27 18:49:06.663 ERROR 8704 — [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : El servlet.service() para el servlet [dispatcherServlet] en el contexto con ruta [] lanzó una excepción [La solicitud ha fallado; la excepción anidada es org.springframework.dao.DataIntegrityViolationException: no se pudo ejecutar la declaración; SQL [n/a]; restricción [null]; excepción anidada es org.hibernate.exception.ConstraintViolationException: no se pudo ejecutar la declaración] con la causa raíz

java.sql.SQLIntegrityConstraintViolationException: No se puede agregar o actualizar una fila secundaria: falla una restricción de clave externa (library.tbl_book_autors, CONSTRAINT fk_tbl_book_authors_tbl_book1 FOREIGN KEY (book_id) REFERENCES tbl_book (id) ON DELETE CASCADE ON UPDATE CASCADE)

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para guardar un libro con sus autores, puedes incluir la lista de autores en el objeto Book y luego guardar el objeto Book usando los métodos EntityManager o CrudRepository:

    Book book = new Book();
    book.setTitle("un nuevo libro");
    Publisher publisher = entityManager.getReference(Publisher.class, 7);
    book.setPublisher(publisher);
    Set<author> authors = new HashSet<>();
    Author author = entityManager.getReference(Author.class, 3);
    authors.add(author);
    book.setAuthors(authors);
    entityManager.persist(book); // o bookRepository.save(book);
    

    En el ejemplo de JSON proporcionado, puedes ver que los IDs del libro y el autor ya están incluidos, por lo que puedes usar entityManager.getReference() para buscar los objetos correspondientes y agregarlos al objeto Book.

    Con respecto a la tabla tbl_book_authors, la anotación @ManyToMany con @JoinTable ya crea esa tabla por ti, por lo que no necesitas crearla manualmente. El error en el registro parece estar relacionado con una restricción de clave externa, así que asegúrate de que las tablas tbl_publisher y tbl_author tengan los datos necesarios y de que los IDs coincidan con los proporcionados en el JSON.

Comments are closed.