Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

CRUD

Oi gente! O metodo remove da componente do Autor lanca a seguinte exception:

HTTP Status 500 - javax.persistence.RollbackException: Error while committing the transaction

type Exception report

message javax.persistence.RollbackException: Error while committing the transaction

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: javax.persistence.RollbackException: Error while committing the transaction
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

javax.faces.el.EvaluationException: javax.persistence.RollbackException: Error while committing the transaction
    javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
    javax.faces.component.UICommand.broadcast(UICommand.java:315)
    javax.faces.component.UIData.broadcast(UIData.java:1092)
    javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:791)
    javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1256)
    com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

javax.persistence.RollbackException: Error while committing the transaction
    org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92)
    br.com.caelum.livraria.dao.DAO.remove(DAO.java:40)
    br.com.caelum.livraria.bean.AutorBean.remover(AutorBean.java:40)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.apache.el.parser.AstValue.invoke(AstValue.java:247)
    org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
    com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
    javax.faces.component.UICommand.broadcast(UICommand.java:315)
    javax.faces.component.UIData.broadcast(UIData.java:1092)
    javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:791)
    javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1256)
    com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`livrariadb`.`livro_autor`, CONSTRAINT `FK9590997AD70C7E4A` FOREIGN KEY (`autores_id`) REFERENCES `autor` (`id`))
    org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
    org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
    org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)
    br.com.caelum.livraria.dao.DAO.remove(DAO.java:40)
    br.com.caelum.livraria.bean.AutorBean.remover(AutorBean.java:40)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.apache.el.parser.AstValue.invoke(AstValue.java:247)
    org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
    com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
    javax.faces.component.UICommand.broadcast(UICommand.java:315)
    javax.faces.component.UIData.broadcast(UIData.java:1092)
    javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:791)
    javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1256)
    com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

org.hibernate.exception.ConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`livrariadb`.`livro_autor`, CONSTRAINT `FK9590997AD70C7E4A` FOREIGN KEY (`autores_id`) REFERENCES `autor` (`id`))
    org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
    org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
    org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    com.sun.proxy.$Proxy56.executeUpdate(Unknown Source)
    org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
    org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3303)
    org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3506)
    org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:100)
    org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:280)
    org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
    org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
    org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
    br.com.caelum.livraria.dao.DAO.remove(DAO.java:40)
    br.com.caelum.livraria.bean.AutorBean.remover(AutorBean.java:40)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.apache.el.parser.AstValue.invoke(AstValue.java:247)
    org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
    com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
    javax.faces.component.UICommand.broadcast(UICommand.java:315)
    javax.faces.component.UIData.broadcast(UIData.java:1092)
    javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:791)
    javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1256)
    com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`livrariadb`.`livro_autor`, CONSTRAINT `FK9590997AD70C7E4A` FOREIGN KEY (`autores_id`) REFERENCES `autor` (`id`))
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    java.lang.reflect.Constructor.newInstance(Unknown Source)
    com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    com.mysql.jdbc.Util.getInstance(Util.java:386)
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1040)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
    com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
    org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    com.sun.proxy.$Proxy56.executeUpdate(Unknown Source)
    org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
    org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3303)
    org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3506)
    org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:100)
    org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:280)
    org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
    org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
    org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
    br.com.caelum.livraria.dao.DAO.remove(DAO.java:40)
    br.com.caelum.livraria.bean.AutorBean.remover(AutorBean.java:40)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    java.lang.reflect.Method.invoke(Unknown Source)
    org.apache.el.parser.AstValue.invoke(AstValue.java:247)
    org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
    com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
    javax.faces.component.UICommand.broadcast(UICommand.java:315)
    javax.faces.component.UIData.broadcast(UIData.java:1092)
    javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:791)
    javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1256)
    com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

note The full stack trace of the root cause is available in the Apache Tomcat/8.0.35 logs.
Apache Tomcat/8.0.35

Aqui esta a view autor.xhtml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

    <ui:composition template="_template.xhtml">
        <ui:define name="titulo">
            Novo Autor
        </ui:define>

        <ui:define name="conteudo">
        <h:form>
            <fieldset>
                <legend>Dados do Autor</legend>
                <h:panelGrid columns="2">
                    <h:outputLabel value="Nome:" for="nome" />
                    <h:inputText id="nome" value="#{autorBean.autor.nome}" />
                    <h:commandButton value="Gravar" action="#{autorBean.gravar}">
                        <f:ajax execute="@form" render="@form :formAutores:tabelaAutores"/>
                    </h:commandButton>
                </h:panelGrid>
            </fieldset>
        </h:form>    

        <h:form id="formAutores">
        <h:dataTable id="tabelaAutores" value="#{autorBean.autores}" var="autor" >
            <h:column>
                <f:facet name="header">NOMES</f:facet>
                <h:outputText value="#{autor.nome}"/>
            </h:column>

            <h:column>
                <f:facet name="header">ALTERAR</f:facet>
                <h:commandLink value="altera" action="#{autorBean.carregar(autor)}"/>
            </h:column>

            <h:column>
                <f:facet name="header">REMOVER</f:facet>
                <h:commandLink value="Remove" action="#{autorBean.remover(autor)}"/>
            </h:column>


        </h:dataTable>
        </h:form>

        </ui:define>        
    </ui:composition>
</html>

E classe AutorBean

package br.com.caelum.livraria.bean;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import br.com.caelum.livraria.dao.DAO;
import br.com.caelum.livraria.modelo.Autor;

@ManagedBean
@ViewScoped
public class AutorBean {

    private Autor autor = new Autor();
    private List<Autor> autores = new ArrayList<Autor>();

    public Autor getAutor() {
        return autor;
    }

    public String gravar() {
        System.out.println("Gravando autor " + this.autor.getNome());
        if(autor.getId()==null) {
        new DAO<Autor>(Autor.class).adiciona(this.autor);
        }
        new DAO<Autor>(Autor.class).atualiza(this.autor);
        return "livro?faces-redirect=true";

    }


    public List<Autor> getAutores(){
        this.autores =  new DAO<Autor>(Autor.class).listaTodos();
        return autores;
    }

    public void remover(Autor autor) {
        new DAO<Autor>(Autor.class).remove(autor);
    }

    public void carregar(Autor autor) {
        this.autor = autor;        
    }
}

Nao termina a transacao, lançando um rollBackException, dado que nao pode alterar a chave estrangeira( FK)

Ja tentei todas manobras possiveis, ainda nao consegui resolver o problema!

5 respostas
solução!

Isso está acontecendo pois lá no banco de dados existe um relacionamento entre as tabelas Autor e Livro. Para resolver o problema é preciso desfazer este relacionamento e só depois você conseguirá excluir o autor.

O relacionamento tem que ser mesmo @ManyToMany, já que Um livro pode ser de vários autores e um Autor pode possuir vários livros.

Na verdade faz sentido o metodo remove(autor) nao aceitar remover um autor ligado a algum livro, senao os livros ficariam sem autor. Porem aceita remover autores que nao estao vinculados a nenhum livro.

Em todo o caso, obrigado pela atencao!

@Cremildo, resolvi esse problema com o seguinte código de forma clara para o usuário:

    public void remover(Autor autor) {
        System.out.println("Removendo autor " + autor.getNome());

        try {
            new DAO<Autor>(Autor.class).remove(autor);
        } catch (RollbackException Exception) {
            FacesContext.getCurrentInstance().addMessage("autor",
                    new FacesMessage("Autor não pode ser excluído por estar associado à um Livro."));
        }
    }

Exacto, assim se resolve o problema de uma pilha de exceptions lançada na cara do usuário "inocente"!

Olá,

Se o relacionamento é Muitos para Muitos, e sabendo que a regra de negócio é um autor pode ter mais de um livro, então pode-se criar um método para retorne a quantidade de livros do autor ou um método que retorne uma lista de livros do autor. Assim no método remover, basta verificar se o autor tem 0 (zero) livros antes de removê-lo, e assim lançar a informação de acordo (como você fez).