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

Falha ao alterar pedido

Olá, estou montando um sistema a partir do que estou aprendendo no curso, mas no meu projeto ao alterar um pedido está apresentando a seguinte mensagem de falha: Caminho: Na pagina ListaPedidos.xhtml... clico no botão "Alterar"... abre a tela AdicionaPedido.xhtml... altero a data... altero o cliente... clico no botão "Salvar"... e apresenta a seguinte mensagem:

An Error Occurred:

org.hibernate.exception.ConstraintViolationException: could not execute statement
- Stack Trace

javax.faces.el.EvaluationException: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:190)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3281)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:158)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:345)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1218)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:421)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at DAO.PedidoDAO.alterarPedido(PedidoDAO.java:38)
    at Bean.PedidoMB.salvaPedido(PedidoMB.java:59)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:279)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:273)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    ... 28 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`pdvdb`.`pedido`, CONSTRAINT `fk_Pedido_1` FOREIGN KEY (`id_cliente`) REFERENCES `cliente` (`idCliente`) ON DELETE CASCADE ON UPDATE CASCADE)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1040)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187)
    ... 51 more

Pelo que entendi, é um erro de integridade devido a estar tentando atualizar por ter um chave estrangeira:

Cannot add or update a child row: a foreign key constraint fails

Mas o que quer fazer é só alterar o "id_cliente" da tabela "pedido", a inclusão funciona normal, só acontece na alteração. Inclusive a exclusão também está funcionando normalmente.

Alguém pode me ajudar, por favor?

Segue o código:

model.Cliente.java


@Entity
@Table(name="cliente")
public class Cliente {

    @Id
    @Column(name="idCliente")
    private int id;
    private String cpf;
    private String nome;
    private String sobrenome;

    public Cliente() {
    }

    public Cliente(Integer id, String cpf, String nome, String Sobrenome) {
        this.id = id;
        this.cpf = cpf;
        this.nome = nome;
        this.sobrenome = sobrenome;
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCpf() {
        return cpf;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getSobrenome() {
        return sobrenome;
    }

    public void setSobrenome(String sobrenome) {
        this.sobrenome = sobrenome;
    }
}

model.Pedido.java

@Entity
@Table(name = "pedido")
public class Pedido implements Serializable {

    @Id
    @Column(name = "idPedido")
    private int Id;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "id_cliente")
    private Cliente cliente;

    private Date data;

    public int getId() {
        return Id;
    }

    public void setId(int Id) {
        this.Id = Id;
    }

    public Cliente getCliente() {
        return cliente;
    }

    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }
}

managedBean do Pedido: Bean.Pedido.java

@ManagedBean
@SessionScoped
public class PedidoMB {
    private Pedido pedido;
    private PedidoDAO pedidoDAO;
    private Cliente cliente;
    private ClienteDAO clienteDAO;

    public PedidoMB() {
    }

    @PostConstruct
    public void init(){
        pedido = new Pedido();
        pedidoDAO = new PedidoDAO();
        cliente = new Cliente();
        clienteDAO = new ClienteDAO();
        pedido.setCliente(this.cliente);
    }

    public List<Pedido> listaPedidos(){
        init();
        return pedidoDAO.listarPedidos();
    }

    public String salvaPedido(){
        this.pedido.setCliente(cliente);
        if(this.pedido.getId() == 0){
            pedidoDAO.salvarPedido(this.pedido);
        }else{
            pedidoDAO.alterarPedido(this.pedido);
        }
        return "ListaPedidos.xhtml";
    }

    public List<Cliente> listaClienteP(){
        return clienteDAO.listaClientes();
    }

    public void onDateSelect(SelectEvent event) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Date Selected", format.format(event.getObject())));
    }

    public void click() {
        RequestContext requestContext = RequestContext.getCurrentInstance();

        requestContext.update("form:display");
        requestContext.execute("PF('dlg').show()");
    }

    public int pegaIdCliente(int clienteId){
        return clienteDAO.getCliente(clienteId).getId();
    }

    public void excluiPedido(Pedido pedido){
        pedidoDAO.excluirPedido(pedido);
    }

    public String alteraPedido(Pedido pedido){
        this.pedido = pedido;
        return "AdicionaPedido.xhtml";
    }

    public Pedido getPedido() {
        return pedido;
    }

    public void setPedido(Pedido pedido) {
        this.pedido = pedido;
    }

    public PedidoDAO getPedidoDAO() {
        return pedidoDAO;
    }

    public void setPedidoDAO(PedidoDAO pedidoDAO) {
        this.pedidoDAO = pedidoDAO;
    }
}

a tela de listagem de pedidos: ListaPedidos.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://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Lista de Pedidos</title>
    </h:head>
    <h:body>
        <h:form>
            <h:dataTable border="1" value="#{pedidoMB.listaPedidos()}" var="pedido">
                <h:commandButton value="Home" action="index.xhtml" />

                <h:column>
                    <f:facet name="header">Excluir</f:facet>
                    <h:commandButton value="Excluir" action="#{pedidoMB.excluiPedido(pedido)}"/>
                </h:column>

                <h:column>
                    <f:facet name="header">Alterar</f:facet>
                    <h:commandButton value="Alterar" action="#{pedidoMB.alteraPedido(pedido)}"/>
                </h:column>

                <h:column>
                    <f:facet name="header">Código</f:facet>
                    <h:outputLabel value="#{pedido.id}" />
                </h:column>

                <h:column>
                    <f:facet name="header">Data</f:facet>
                    <h:outputLabel value="#{pedido.data}">
                        <f:convertDateTime pattern="dd/MM/yyyy"/>
                    </h:outputLabel>
                </h:column>

                <h:column>
                    <f:facet name="header">Cliente</f:facet>
                    <h:outputLabel value="#{pedido.cliente.nome}"/>
                </h:column>

            </h:dataTable>

            <h:commandButton value="Incluir um novo Pedido" action="AdicionaPedido.xhtml"/>
        </h:form>
    </h:body>
</html>

e a tela que salva (adiciona ou altera) os pedidos: AdicionaPedido.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://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <p:panel>
           Id <h:inputText value="#{pedidoMB.pedido.id}" /><br/>
           <p:outputLabel for="calendario" value="data: " />
           <p:calendar id="calendario" value="#{pedidoMB.pedido.data}" showOn="button" pattern="dd/MM/yyyy"/><br/>

           <p:outputLabel for="nomeCliente" value="Cliente: " />
           <p:selectOneMenu id="nomeCliente" value="#{pedidoMB.pedido.cliente.id}" style="width:125px">
                <f:selectItems value="#{pedidoMB.listaClienteP()}" 
                               var="nomeCliente"
                               itemLabel="#{nomeCliente.nome}" 
                               itemValue="#{nomeCliente.id}" />
            </p:selectOneMenu>

           <br/><h:commandButton value="Salvar" action="#{pedidoMB.salvaPedido()}"/>
           </p:panel>
        </h:form>
    </h:body>
</html>

Estou achando que é algum erro no mapeamento das classes, mas não estou conseguindo entender o que é pra ser feito. Já tentei algumas soluções que encontrei em alguns fóruns com que tinhas problemas parecidos, mas nenhum resolveu.

Desde já agradeço toda ajuda.

3 respostas
solução!

Marciel,

Esse erro acontece porque está tentando atualizar o pedido com um id_cliente inválido, ou seja, o novo cliente que você está tentando informar não está cadastrado na tabela Cliente (não possui um id).

Você só pode alterar o cliente de um pedido, por um outro cliente que esteja previamente cadastrado.

É estranho, porque aparentemente seu código está correto. Debuga teu código merge na classe PedidoDAO e vê se tá chegando o id_cliente.

Olá Manoel deu certo, agora está funcionando a alteração também.

Não estava chegando a variável do cliente no PedidoDAO, no momento de passagem de uma tela da listagem para a de adicionar estava, mas quando chegava no DAO se perdia.

Ai parei de focar no mapeamento e comecei a acompanhar as variáveis pra ver onde estava se perdendo. E encontrei.

Ajustei no momento de salvar de:

public String salvaPedido(){
        this.pedido.setCliente(cliente);
        if(this.pedido.getId() == 0){
            pedidoDAO.salvarPedido(this.pedido);
        }else{
            pedidoDAO.alterarPedido(this.pedido);
        }
        return "ListaPedidos.xhtml";
    }

Para:

public String salvaPedido(){

        if(this.pedido.getId() == 0){
            pedidoDAO.salvarPedido(this.pedido);
        }else{
            pedidoDAO.alterarPedido(this.pedido);
        }
        return "ListaPedidos.xhtml";
    }

retirei a linha do

this.pedido.setCliente(cliente);

achei que ela era necessária para inclusão, mas testei a inclusão e ainda funciona normalmente. Todo o Crud de pedido está funcionando agora =D.

Muito obrigado Manoel, valeu.

Beleza!

Bons estudos!

Abraço.