EJB Persistência

Caros,

Tenho uma tabela Cliente e uma telefone. Na lógica um cliente pode ter N telefones.

PESSOA
id (auto-incremento)
nome (string)

TELEFONE
id (auto_incremento)
id_pessoa(FK)
numero (String)

Criei um Module EJB pelo Netbeans 6.8 e consigo fazer a persistência tranquilamente de PESSOA.
Tenho uma dúvida de como gravar os dados na tabela Telefone.

PESSOA

public void adicionar(String nome) throws Exception {
try {

        Pessoa pessoa = new Pessoa();
        pessoa.setNome(nome);
        em.persist(pessoa);

    } catch (Exception e) {
        throw new UnsupportedOperationException("Erro:" + e.getMessage());
    }
}

Só que o ID dessa tabela é auto-incremento, eu teria que pegar esse ID e gravar na tabela de telefone e mais o número.
Só que não sei como proceder para gravar o telefone.

Minha classe PESSOA está assim:

@Entity
@Table(name = “pessoa”)
@NamedQueries({
@NamedQuery(name = “Pessoa.find”, query = "SELECT p FROM Pessoa p WHERE p.pesCnpjCpf = :cnpjcpf ")
})
public class Pessoa implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = “id”, nullable = false)
private Integer id;
@Column(name = “nome”)
private String nome;

@OneToMany(cascade=CascadeType.ALL, mappedBy="pessoa")
private Collection<Telefone> telefone;

public Pessoa() {
}

--refactor dos campos (não coloquei )--


public Collection<Telefone> getTelefone() {
    return telefone;
}

public void setTelefone(Collection<Telefone> telefone) {
    this.telefone = telefone;
}

}

Minha classe TELEFONE está assim:

@Entity
@Table(name = “telefone”)
@NamedQueries({
@NamedQuery(name = “PessoaFone.findAll”, query = “SELECT p FROM Telefone p”)
})
public class PessoaFone implements Serializable {
private static final long serialVersionUID = 1L;

@ManyToOne()
@JoinColumn(name = "id", referencedColumnName = "id", insertable = false, updatable = false)
private Pessoa pessoa;

public PessoaFone() {
}


public Pessoa getPessoa() {
    return pessoa;
}

public void setPessoa(Pessoa pessoa) {
    this.pessoa = pessoa;
}

}

Minha dúvida: É como ao adicionar a pessoa, eu automaticamente já inserir os dados na tabela de telefone? Lembrando que na tabela de telefone eu preciso do ID que será gerado (auto-incremento) após inserir a pessoa.

Valeu!! QQ ajuda será bem-vinda.

Olá!

Isso é feito automaticamente. (pelo menos utilizando o toplink)
Apenas utilize o metodo setTelefone(Collection telefone) passando a lista de telefones para o cliente.

att,

Marck,

Obrigado pela resposta, mas a minha dúvida é a seguinte:

Eu tentei fazer dessa maneira no método adicionar. Como telefone é uma Collection, eu populei um manualmente:

public void adicionar(String nome) throws Exception {
try {

//esse foi o teste (so que no param, EU NAO TENHO PQ ELE VAI SER GERADO AINDA, entao nao sei como funciona)
Telefone telefone = new Telefone(param);
telefone.setNumero("123456");

List<Telefone> fones = new ArrayList<Telefone>();
fones.add(telefone);

//---fim da criacao manual do teste

Pessoa pessoa = new Pessoa();
pessoa.setNome(nome);
//na linha de baixo ele espera uma collection
pessoa.setTelefone(fones)

em.persist(pessoa);

} catch (Exception e) {
throw new UnsupportedOperationException("Erro:" + e.getMessage());
}
} 

Não estou entendendo como passar uma Collection sendo que para instanciar eu preciso do ID da outra tabela que nem gerado foi ainda.

Então, é que a sua Unidade de Persistencia se encarrega disto.

Eu não sei qual UP você está usando, mas pelo menos no toplink da oracle é deste jeito: ele se encarrega de gerar as chaves e passar para as tabelas filhas na hora de persistir.

Tá gerando algum erro quando vc chama o persist? Ou simplesmente não salva no banco?

Cara vc acertou quase tudo. Tem certeza que vc tentou, ao menos, rodar esse código
antes de posta-lo aqui? Eu mesmo já me peguei varias vezes procurando na net
soluções p/ problemas que eu nem tinha certeza que existiam.

Bom, de qualquer forma, o código que vc escreveu está corréto. Vc pode tanto passar
uma lista de objetos como criar um método “adicionar(Telefone)” em Pessoa para
fazer isso por vc. Apenas tenha consiência de algumas coisas:

1 - o objeto Telefone que vc está vinculando com a Pessoa precisa já estar gravado
na base. Ele precisa já ter um id (não null).

2 - no caso do uso do CascadeType.ALL, basta que vc de um merge(Pessoa) ou
persist(Pessoa).

Não procure entender JPA como um Banco Relacional. Tente olhar p/ ele com uma
coleção de objetos (como um List). Inclusive eu aconselho que vc deixe que o Toplink
(ou qualquer outro provider que vc estiver utilizando) crie as tabelas p/ vc, e evite o
uso de anotações como “Table” e “Column”. Procure lidar com os objetos como
quaisquer outros objetos do seu sistema e deixe que o provider cuide da base de dados.

Olá Rafael,

Eu não testei ainda pq eu não entendi como instanciar TELEFONE pq ele precisa do ID da pessoa e como vou ter o ID se ainda não persist pessoa? Só depois de persist isso que vou ter o ID (gerado auto-incremento).

Obrigado pela ajuda.

Rafael,

Eu fiz o teste aqui e tá funcionando a Collection a única coisa que está dando erro eh no seguinte. Ele não consegue pegar o ID da pessoa.
Então no log tem isso:

 insert or update on table "telefone" violates foreign key constraint "FK_pessoa"
  Detail: Key (telefone)=(0) is not present in table "pessoa".
Error Code: 0
Call: INSERT INTO telefone (id_pessoa, numero) VALUES (?, ?)
        bind => [0, 123456]

Dúvida: Eu primeiro preciso persistir pessoa? ou tem algum jeito de mandar o ID da pessoa para essa collection pq meu código está assim:

            Pessoa pessoa = new Pessoa();

            //telefone
            Telefone telefone = new Telefone();
            telefone.setIdPessoa(pessoa);
            telefone.setNumero("123456");

            //collection
            List<Telefone> fones = new ArrayList<Telefone>();
            fones.add(telefone);

            pessoa.setNome(nome);
            pessoa.setTelefone(fones);
            em.persist(pessoa);

Descobri o problema.

em.persist(pessoa);
em.flush();

System.out.print("ID: "+ pessoa.getId());

Depois de persistir eu fiz um em.flush() e ae o ID está retornando.

Cara, eu rodei o mesmo código que vc postou ai em cima e foi de boa!!!
Nem um errinho!!! É claro que eu tive q adicionar algumas coisas que vc
omitiu no código postado. Não precisei o flush() (o que é muito util já que é
uma linha a menos de código).

Caso vc queira o código do projeto me envie um e-mail.