Ir ao conteúdo
  • Cadastre-se

Java JSF, Hibernate - Foreign key is Null!


Posts recomendados

Sou iniciante em java e estou com um problema aqui que eu sei que deve ser coisa besta, mas meu cérebro está bloqueado.
Estou fazendo um crud simples com 2 classes com o relacionamento OneToMany: Pessoa 1:n Telefone.

Tenho uma página com o form de cadastro de pessoas e abaixo do form tenho uma dataTable que lista as pessoas cadastradas(Usei o criteria pra buscar os dados no banco e armazenar numa List). Clicando em uma das pessoas eu entro em outra página com um formulário para cadastrar telefones dessa pessoa.
Esse formulário está cadastrando os telefones no banco, só que a coluna pessoa_id, que é a foreign key sempre fica como null. Como posso fazer o Hibernate enxergar PK de Escolas e cadastra-la como FK na tabela Provas?
Tentei um milhão de formas e sempre dá errado. As informações que encontrei na internet a respeito só me deixaram mais confuso porque o pessoal sempre usa uma aplicação java comum e faz o teste inserindo o id manualmente ao criar o objeto. Eu preciso da lógica pra que tudo seja feito a partir de um formulário.

Desde já obrigado =)


Classe Pessoa:

@Entity
public class Pessoa implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String nome;
    @OneToMany(mappedBy = "pessoa", targetEntity = Telefone.class, cascade = CascadeType.ALL)
    private List<Telefone> telefones;
    ...

Classe Telefone:

@Entity
public class Telefone implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String telefone;
    @ManyToOne
    @JoinColumn(name = "pessoa_id")
    private Pessoa pessoa;
    ...


Dao Telefone

public void addTelefone(Telefone t) {
        try {
            sessao = HibernateUtil.getSessionFactory().openSession();
            transacao = sessao.beginTransaction();
            Pessoa pessoas = new Pessoa();
            Telefone telefone = new Telefone();
        
            telefone.setId(t.getId());
            telefone.setTelefone(t.getTelefone());
            telefone.setPessoa(t.getPessoa());
            sessao.save(telefone);
            transacao.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sessao.close();
        }
    }

 

Link para o comentário
Compartilhar em outros sites

O velho caso do Relacionamento Bidirecional ... é terrível e gera vários erros mesmo ... 

Não é elegante fazer isso, mas meu sono não me deixa pensar em algo melhor ...
 

public void addTelefone(Pessoa pessoa, Telefone telefone) {
        try {
            sessao = HibernateUtil.getSessionFactory().openSession();
            if (pessoa.getTelefones() == null) {
				pessoa.setTelefones(new ArrayList<Telefone>());
			}
            pessoa.getTelefones().add(telefone);
            telefone.setPessoa(pessoa);
            sessao.save(telefone);
            transacao.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sessao.close();
        }
    }

O Problema do bidirecional é que ele tem problemas para entender que quando você seta um, implicitamente você está setando o outro ... Forçando dessa forma, você garante que o mesmo objeto está sendo setado nos dois lados ...

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Obrigado pela resposta.

Cara, eu entendi a parte que eu devo colocar um addTelefone no objeto Pessoa, mas não entendi muito bem como essa pessoa seria resgatada dessa forma.
Fuçando um pouco no google eu consegui uma forma de resolver esse problema da fk.
Eu deveria ter colocado as páginas xhtml e o bean pra ficar mais claro.. erro meu.

Aqui está o form que cadastra as pessoas. Eu adicionei no nome o <f:setPropertyActionListener pra enviar o objeto pessoa pro meu telefoneBean. (Não sei se isso é uma boa prática, mas funcionou)

<h:form>
                Cadastro de Pessoas<br/>
                <h:panelGrid columns="2">
                    Nome: <h:inputText id="nomeTxt" value="#{pessoaBean.pessoa.nome}"/>
                    <h:inputHidden/>
                    <h:commandButton value="Cadastrar" action="#{pessoaBean.adicionarPessoa}"/>
                </h:panelGrid><br/>
                Pessoas Cadastradas<br/>
                <h:dataTable value="#{pessoaBean.listarPessoas()}" var="listaDePessoas" border="1">
                    <h:column>
                        <f:facet name="header">
                            Id
                        </f:facet>
                        <h:outputText value="#{listaDePessoas.id}"/>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Nome
                        </f:facet>
                        <h:commandLink value="#{listaDePessoas.nome}" action="#{pessoaBean.carregarPessoa(listaDePessoas)}">
                            <f:setPropertyActionListener target="#{telefoneBean.telefone.pessoa}" value="#{listaDePessoas}"/>
                        </h:commandLink>
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            Ações
                        </f:facet>
                        <h:commandLink value="Excluir" action="#{pessoaBean.removerPessoa(listaDePessoas)}"/>
                    </h:column>

                </h:dataTable>

            </h:form>

image.png.dfb56368191c1f58a7aed4ac93d3164f.png

Eu criei essa lista usando Criteria no PessoaDao e recebo a lista no PessoaBean.
Clicando ali numa pessoa venho pra essa página:

 

           <h:form>
                <h:panelGrid columns="2">
                    Id: <h:outputText value="#{pessoaBean.pessoa.id}"/>
                    Nome: <h:outputText value="#{pessoaBean.pessoa.nome}"/>
                </h:panelGrid>
                Cadastro de Telefones<br/>
                <h:panelGrid columns="2">
                    Telefone: <h:inputText id="telefoneTxt" value="#{telefoneBean.telefone.telefone}"/>
                    <h:inputHidden/>
                    <h:commandButton value="Cadastrar" action="#{telefoneBean.adicionarTelefone()}"/>
                </h:panelGrid><br/>
            </h:form>

image.png.bf73d6e1f2f724a5a499ce94e90577a4.png

 

Cadastrando o telefone aí ele fica com a foreign key correta. 
O problema agora é que eu preciso atualizar o objeto Pessoa adicionando esse telefone na lista. Nessa sua sugestão, eu não precisaria fazer um sessao.update(pessoa); ? Se eu faço isso, ele me diz que eu preciso de outra sessão.
O Dao ficou assim

public void addTelefone(Telefone t) {
        try {
            sessao = HibernateUtil.getSessionFactory().openSession();
            transacao = sessao.beginTransaction();

            Telefone telefone = new Telefone();        
            telefone.setId(t.getId());
            telefone.setTelefone(t.getTelefone());
            telefone.setPessoa(t.getPessoa());

            sessao.save(telefone);
            transacao.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sessao.close();
        }
    }

Método no TelefoneBean (Os beans estão como @SessionScoped não sei se isso interfere em algo)

 public String adicionarTelefone() {
        telefoneDao.addTelefone(telefone);
        return "index";
    }



Uma coisa que eu notei é que no meu banco, na tabela Pessoa, não existe a coluna dos telefones. Não deveria aparecer essa coluna ao criar uma pessoa nem que fosse como null?
 

image.png.7971fd3e1b5da0dc6b297446bf79f631.png

 

 

 

 

 

 

 

 

Link para o comentário
Compartilhar em outros sites

@psykotico Sim, mas eu coloquei isso no form só pra facilitar a visualização. Por isso estão como outputText.
Eu só uso o que está no input mesmo.

Eu pensei em colocar num inputHidden pra recuperar o id. Mas acho que seria mais gambiarra do que o que eu fiz.
o f:setPropertyActionListener já manda o objeto pro telefoneBean.pessoa, eu consigo resgata-lo no meu objeto 'Telefone t' usando t.getPessoa. Então não é necessário pegar esse id, a menos que eu precise dele pra buscar pessoa no banco e atualizar. É isso?

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@psykotico acho que acabei entendendo mais rápido depois de virar 3 noites procurando uma solução pra isso.. kkk

de qualquer forma, ainda não sei recuperar o valor de um input que não seja uma variável de uma classe mapeada. Não posso setar o id de uma pessoa como objeto pessoa da classe Telefone porque são tipos diferentes.

Você sabe como eu deveria modificar o addTelefone() pra que ele busque o objeto 'pessoa' no banco e atualize "ao mesmo tempo" que salva o telefone?
 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...