JPA - Persistir numa tabela que tenha uma FK

10 respostas
hbdias
Bom dia pessoal, estou com um problema para inserir um condômino através do JPA que não consigo decifrar há muito tempo. Tenho duas tabelas: Condômino(cliente) e Apartamento. Um Apartamento pode ter vários condôminos. Abaixo descrevo minhas tabelas criadas no PostgreSQL:
-- Table: condômino
CREATE TABLE condomino
(
  con_codigo integer NOT NULL,
  con_cpf character(11),
  con_email character varying(50),
  con_password character(6),
  cod_apto integer,
  fun_nivel character(1),
  con_nome character varying(100),
  CONSTRAINT condomino_pkey PRIMARY KEY (con_codigo),
  CONSTRAINT apartamento_apa_codigo_fkey FOREIGN KEY (cod_apto)
      REFERENCES apartamento (apa_codigo) MATCH FULL
      ON UPDATE NO ACTION ON DELETE NO ACTION
) 
WITHOUT OIDS;
-- Table: apartamento
CREATE TABLE apartamento
(
  apa_codigo integer NOT NULL,
  apa_num integer,
  tor_codigo integer,
  CONSTRAINT apartamento_pkey PRIMARY KEY (apa_codigo),
  CONSTRAINT apartamento_tor_codigo_fkey FOREIGN KEY (tor_codigo)
      REFERENCES torre (tor_codigo) MATCH FULL
      ON UPDATE NO ACTION ON DELETE NO ACTION
) 
WITHOUT OIDS;

Estou inserindo através do web services, mas me dá um erro gigante no qual tudo indica que há algum valor NULL.

@WebService(serviceName = "GerenciarEncomendasWsApp")
@Stateless()
public class GerenciarEncomendasWsApp {
    @EJB
    CondominoFacadeRemote condominoFacadeBean;
    
    @WebMethod(operationName = "cadastrarCondomino")
    public void cadastrarCondomino(@WebParam(name = "cpf") String cpf, @WebParam(name = "email") String email, @WebParam(name = "password") String password, @WebParam(name = "codapto") Integer codapto, @WebParam(name = "nivelAcesso") String nivel, @WebParam(name = "nome") String nome) {
        //TODO write your implementation code here:
        condominoFacadeBean.adicionar(cpf, email, password, codapto, nivel, nome);
    }

Já tentei passar valores direto(sem variáveis) para ver se insere, mas nada deu certo! Eu acredito que a forma como estou fazendo para inserir na tabela com a FK (ManyToOne) está errada. Outra tabela que não tem FK insere normalmente. Poderiam me ajudar?

Principais dúvidas:

1. Como faço para inserir um registro na tabela condomino tendo em vista que a tabela Apartamento já possui o registro (seria tipo multivalorados)?

2. A forma como estou fazendo na classe CondominoFacade para inserir um registro na tabela condomino está correto?

Obrigado!

A Classe CondominoFacade

public class CondominoFacade implements CondominoFacadeRemote, CondominoFacadeLocal {
    
    @PersistenceContext
    private EntityManager em;    
    @Override
    public void adicionar(String cpf, String email, String password, Integer codapto, String nivel, String nome) {
        Condomino condomino = new Condomino();      
        
        condomino.setConCodigo(gerarNovoCodigo());
        condomino.setConCpf(cpf);
        condomino.setConEmail(email);
        condomino.setConPassword(password);        
        condomino.setConNivel(nivel);
        condomino.setConNome(nome);       
        
        Apartamento apartamento = new Apartamento();
        apartamento.setApaCodigo(codapto);        
        condomino.setApaCodigo(apartamento);
        em.persist(condomino);
        
        //em.flush();
    }

    @Override
    public int gerarNovoCodigo() {
        String s;
        int n;
        if(em.createNamedQuery("Condomino.findAll").getResultList().isEmpty()){
            n=0;
        }else{
            s = em.createNamedQuery("Condomino.getMaxCodigo").getSingleResult().toString();
            n = Integer.parseInt(s);
        }
        return n+1;
    }
   . Mais coisas aqui
   .
   .
}

Classe Condômino

@Entity
@Table(name = "condomino",catalog = "", schema = "public")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Condomino.getMaxCodigo", query = "SELECT MAX(c.conCodigo) FROM Condomino c"),    
    @NamedQuery(name = "Condomino.findAll", query = "SELECT c FROM Condomino c"),
    @NamedQuery(name = "Condomino.findByConCodigo", query = "SELECT c FROM Condomino c WHERE c.conCodigo = :conCodigo"),
    @NamedQuery(name = "Condomino.findByConCpf", query = "SELECT c FROM Condomino c WHERE c.conCpf = :conCpf"),
    @NamedQuery(name = "Condomino.findByConEmail", query = "SELECT c FROM Condomino c WHERE c.conEmail = :conEmail"),
    @NamedQuery(name = "Condomino.findByConPassword", query = "SELECT c FROM Condomino c WHERE c.conPassword = :conPassword"),
    @NamedQuery(name = "Condomino.findByConNivel", query = "SELECT c FROM Condomino c WHERE c.conNivel = :conNivel"),
    @NamedQuery(name = "Condomino.findByNome", query = "SELECT c FROM Condomino c WHERE c.conNome = :conNome")})
public class Condomino implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "con_codigo")
    private Integer conCodigo;
    @Size(max = 11)
    @Column(name = "con_cpf")
    private String conCpf;
    @Size(max = 20)
    @Column(name = "con_email")
    private String conEmail;
    @Size(max = 6)
    @Column(name = "con_password")
    private String conPassword;    
    @JoinColumn(name = "condomino.cod_apto", referencedColumnName = "apartamento.apa_codigo")
    @ManyToOne(optional = true)
    private Apartamento apaCodigo;
    @OneToMany(mappedBy = "conCodigo")
    private Collection<Encomenda> encomendaCollection;
    @Size(max = 1)
    @Column(name = "con_nivel")
    private String conNivel;
    @Size(max = 100)
    @Column(name = "con_Nome")
    private String conNome;   
    public Condomino() {
    }

    public Condomino(Integer conCodigo) {
        this.conCodigo = conCodigo;
    }

    public Integer getConCodigo() {
        return conCodigo;
    }

    public void setConCodigo(Integer conCodigo) {
        this.conCodigo = conCodigo;
    }

    public String getConCpf() {
        return conCpf;
    }

    public void setConCpf(String conCpf) {
        this.conCpf = conCpf;
    }

    public String getConEmail() {
        return conEmail;
    }

    public void setConEmail(String conEmail) {
        this.conEmail = conEmail;
    }

    public String getConPassword() {
        return conPassword;
    }

    public void setConPassword(String conPassword) {
        this.conPassword = conPassword;
    }

    public Apartamento getApaCodigo() {
        return apaCodigo;
    }

    public void setApaCodigo(Apartamento apaCodigo) {
        this.apaCodigo = apaCodigo;
    }

    @XmlTransient
    public Collection<Encomenda> getEncomendaCollection() {
        return encomendaCollection;
    }

    public void setEncomendaCollection(Collection<Encomenda> encomendaCollection) {
        this.encomendaCollection = encomendaCollection;
    }
    public void setConNivel(String conNivel) {
        this.conNivel = conNivel;
    }

    public String getConNivel() {
        return conNivel;
    }
    public void setConNome(String conNome) {
        this.conNome = conNome;
    }

    public String getConNome() {
        return conNome;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (conCodigo != null ? conCodigo.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Condomino)) {
            return false;
        }
        Condomino other = (Condomino) object;
        if ((this.conCodigo == null && other.conCodigo != null) || (this.conCodigo != null && !this.conCodigo.equals(other.conCodigo))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "org.ws.gerencdeencomendas.model.Condomino[ conCodigo=" + conCodigo + " ]";
    }

Classe Apartamento Gerada
    
}
package org.ws.gerencdeencomendas.model;

import java.io.Serializable;
import java.util.Collection;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
/**
 * @author Administrador
 */
@Entity
@Table(name = "apartamento",catalog = "", schema = "public")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Apartamento.findAll", query = "SELECT a FROM Apartamento a"),
    @NamedQuery(name = "Apartamento.findByApaCodigo", query = "SELECT a FROM Apartamento a WHERE a.apaCodigo = :apaCodigo"),
    @NamedQuery(name = "Apartamento.findByApaNum", query = "SELECT a FROM Apartamento a WHERE a.apaNum = :apaNum")})
public class Apartamento implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "apa_codigo")
    private Integer apaCodigo;
    @Column(name = "apa_num")
    private Integer apaNum;
    @JoinColumn(name = "tor_codigo", referencedColumnName = "tor_codigo")
    @ManyToOne
    private Torre torCodigo;
    @OneToMany(mappedBy = "apaCodigo")
    private Collection<Condomino> condominoCollection;
    @OneToMany(mappedBy = "apaCodigo")
    private Collection<Encomenda> encomendaCollection;

    public Apartamento() {
    }

    public Apartamento(Integer apaCodigo) {
        this.apaCodigo = apaCodigo;
    }

    public Integer getApaCodigo() {
        return apaCodigo;
    }

    public void setApaCodigo(Integer apaCodigo) {
        this.apaCodigo = apaCodigo;
    }

    public Integer getApaNum() {
        return apaNum;
    }

    public void setApaNum(Integer apaNum) {
        this.apaNum = apaNum;
    }

    public Torre getTorCodigo() {
        return torCodigo;
    }

    public void setTorCodigo(Torre torCodigo) {
        this.torCodigo = torCodigo;
    }

    @XmlTransient
    public Collection<Condomino> getCondominoCollection() {
        return condominoCollection;
    }

    public void setCondominoCollection(Collection<Condomino> condominoCollection) {
        this.condominoCollection = condominoCollection;
    }

    @XmlTransient
    public Collection<Encomenda> getEncomendaCollection() {
        return encomendaCollection;
    }

    public void setEncomendaCollection(Collection<Encomenda> encomendaCollection) {
        this.encomendaCollection = encomendaCollection;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (apaCodigo != null ? apaCodigo.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Apartamento)) {
            return false;
        }
        Apartamento other = (Apartamento) object;
        if ((this.apaCodigo == null && other.apaCodigo != null) || (this.apaCodigo != null && !this.apaCodigo.equals(other.apaCodigo))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "org.ws.gerencdeencomendas.model.Apartamento[ apaCodigo=" + apaCodigo + " ]";
    }
    
}

10 Respostas

Hebert_Coelho

Então vamos fazer o seguinte, posta o erro completo aí. [=

hbdias

Olá jakefrog, segue o erro apresentado quando tente inserir.

cadastrarCondomino Method invocation

Method parameter(s)
Type Value
java.lang.String [telefone removido]
java.lang.String [email removido]
java.lang.String 123456
java.lang.Integer 1
java.lang.String 1
java.lang.String Nometeste
Service invocation threw an exception with message : null; Refer to the server log for more details

Exceptions details : java.lang.reflect.InvocationTargetException
javax.servlet.ServletException: java.lang.reflect.InvocationTargetException at org.glassfish.webservices.monitoring.WebServiceTesterServlet.doPost(WebServiceTesterServlet.java:330) at org.glassfish.webservices.monitoring.WebServiceTesterServlet.invoke(WebServiceTesterServlet.java:106) at org.glassfish.webservices.EjbWebServiceServlet.service(EjbWebServiceServlet.java:114) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at com.sun.grizzly.http.servlet.ServletAdapter$FilterChainImpl.doFilter(ServletAdapter.java:1002) at com.sun.grizzly.http.servlet.ServletAdapter$FilterChainImpl.invokeFilterChain(ServletAdapter.java:942) at com.sun.grizzly.http.servlet.ServletAdapter.doService(ServletAdapter.java:404) at com.sun.grizzly.http.servlet.ServletAdapter.service(ServletAdapter.java:354) at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:168) at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:238) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) at com.sun.grizzly.ContextTask.run(ContextTask.java:71) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) at java.lang.Thread.run(Thread.java:619) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.glassfish.webservices.monitoring.WebServiceTesterServlet.doPost(WebServiceTesterServlet.java:301) ... 24 more Caused by: javax.xml.ws.soap.SOAPFaultException: javax.ejb.EJBTransactionRolledbackException at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:193) at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:126) at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:123) at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93) at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:144) at $Proxy337.cadastrarCondomino(Unknown Source) ... 29 more
Hebert_Coelho

Se você fizer um debug vc consegue ver se tem algum valor null?

hbdias

jakefrog, fazendo o debug descobri que o erro está no retorno do método gerarNovoCodigo : ele não retorna.

public void adicionar(String cpf, String email, String password, Integer codapto, String nivel, String nome) {
        Condomino condomino = new Condomino();      
        condomino.setConCodigo(gerarNovoCodigo());
        condomino.setConCpf(cpf);
        condomino.setConEmail(email);

Esse método pertence a Classe CondominoFacade que postei anteriormente. Ele pára justamente no if que verifica se a tabela está vazia. Provavelmente o erro está aí, mas não consigo identificar nada de errada no mapeamento da minha classe. Tem alguma idéia do que pode ser?

public int gerarNovoCodigo() { String s; int n; if(em.createNamedQuery("Condomino.findAll").getResultList().isEmpty()){ n=0; }else{ s = em.createNamedQuery("Condomino.getMaxCodigo").getSingleResult().toString(); n = Integer.parseInt(s); } return n+1; }

Hebert_Coelho

E qual if ele para ou dá erro? Ele tem que retornar algo, se ele não está retornando é pq aconteceu algum erro.

hbdias

O if é esse:

Tudo indica que está no acesso ao banco. Só não sei como vou descobrir isso.

Hebert_Coelho

Faz assim: try{ if(em.createNamedQuery("Condomino.findAll").getResultList().isEmpty()){ n=0; }else{ s = em.createNamedQuery("Condomino.getMaxCodigo").getSingleResult().toString(); n = Integer.parseInt(s); } } catch (Exception ex){ ex.printStackTrace(); n=0; }Depois posta o erro aqui.
Pode ser eu entitymanager que está null.

hbdias
O erro é esse:
Service invocation threw an exception with message : null; Refer to the server log for more details

Exceptions details : java.lang.reflect.InvocationTargetException

javax.servlet.ServletException: java.lang.reflect.InvocationTargetException at org.glassfish.webservices.monitoring.WebServiceTesterServlet.doPost(WebServiceTesterServlet.java:330) at org.glassfish.webservices.monitoring.WebServiceTesterServlet.invoke(WebServiceTesterServlet.java:106) at org.glassfish.webservices.EjbWebServiceServlet.service(EjbWebServiceServlet.java:114) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at com.sun.grizzly.http.servlet.ServletAdapter$FilterChainImpl.doFilter(ServletAdapter.java:1002) at com.sun.grizzly.http.servlet.ServletAdapter$FilterChainImpl.invokeFilterChain(ServletAdapter.java:942) at com.sun.grizzly.http.servlet.ServletAdapter.doService(ServletAdapter.java:404) at com.sun.grizzly.http.servlet.ServletAdapter.service(ServletAdapter.java:354) at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:168) at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:238) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) at com.sun.grizzly.ContextTask.run(ContextTask.java:71) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) at java.lang.Thread.run(Thread.java:619) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.glassfish.webservices.monitoring.WebServiceTesterServlet.doPost(WebServiceTesterServlet.java:301) ... 24 more Caused by: javax.xml.ws.soap.SOAPFaultException: javax.ejb.EJBTransactionRolledbackException at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:193) at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:126) at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:123) at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93) at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:144) at $Proxy589.cadastrarCondomino(Unknown Source) ... 29 more
Hebert_Coelho

Troca a linha ex.printStackTrace(); por System.err.println("Mensagem de erro é: " + ex.getMessage() );

Pq tá muito bizarro isso aí viu.

hbdias

Tô tentando mas nao to conseguindo. Como uso web services, qdo faço isso a console não mostra nada. A mensagem só é mostrada na página de teste do web services, aquela msg bizarra.

Criado 1 de maio de 2012
Ultima resposta 1 de mai. de 2012
Respostas 10
Participantes 2