Como salvar no banco uma coleção, usando Hibernate, SQL Server 2008 e Netbeans

5 respostas
Jackye

Olá!

Estou com uma grande dificuldade!
Estou desenvolvendo um sistema de biblioteca.
Na questão de cadastrar obra, temos que ver o relacionamento que existe entre obra e autor, ou seja, tem uma relação no BD de muitos pra muitos, isto é:
Uma obra tem muitos autores e um autor tem muitas obras

Seguindo este conceito tenho a uma interface gráfica para cadastrar obra (Veja anexo.)

Como faço para pegar as linhas da tabela e salvar no banco? Pois na classe obra e autor existe um collection. Veja as classes Java: OBRA:
package Dominio;

import Dominio.Exemplar;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "Obra", catalog = "dbTestesRegras", schema = "dbo")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Obra.findAll", query = "SELECT o FROM Obra o"),
    @NamedQuery(name = "Obra.findByCodObra", query = "SELECT o FROM Obra o WHERE o.codObra = :codObra"),
    @NamedQuery(name = "Obra.findByTitulo", query = "SELECT o FROM Obra o WHERE o.titulo = :titulo")})
public class Obra implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "CodObra", nullable = false)
    private Integer codObra;
    @Column(name = "Titulo", length = 30)
    private String titulo;
    @Basic(optional = false)
    @Column(name = "NuExemplar", nullable = false)
    private int nuExemplar;
    
//Este é o relacionamento de obra com autor:
    //O FetchType.LAZY significa que o conteúdo da super classe será trazido apenas na primeira solicitação. 
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "ObraAutor", joinColumns = {
        @JoinColumn(name = "CodObra")},
    inverseJoinColumns = {
        @JoinColumn(name = "CodAutor")})
    //O Annotation Cascade mostra uma opção de executar todos os comandos nas classes relacionadas.
    @Cascade(CascadeType.ALL)
    private Collection<Autor> autor = new ArrayList<Autor>();
    
    @OneToMany(mappedBy = "codObra")
    @Cascade(CascadeType.SAVE_UPDATE)
    private Collection<Exemplar> exemplar = new ArrayList<Exemplar>();
    
    public Obra() {
    }

    public Obra(Integer codObra) {
        this.codObra = codObra;
    }

    public Integer getCodObra() {
        return codObra;
    }

    public void setCodObra(Integer codObra) {
        this.codObra = codObra;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public int getNuExemplar() {
        System.out.println("passou aqui no get: " + nuExemplar);
        return nuExemplar;
    }

    public void setNuExemplar(int nuExemplar) {
        System.out.println("passou aqui no set: " + nuExemplar);
        this.nuExemplar = nuExemplar;

    }

    @XmlTransient
    public Collection<Autor> getAutor() {
        return autor;
    }

    public void setAutorCollection(Collection<Autor> autor) {
        this.autor = autor;
    }

    @XmlTransient
    public Collection<Exemplar> getExemplar() {
        return exemplar;
    }

    public void setExemplar(Collection<Exemplar> exemplar) {
        this.exemplar = exemplar;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (codObra != null ? codObra.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 Obra)) {
            return false;
        }
        Obra other = (Obra) object;
        if ((this.codObra == null && other.codObra != null) || (this.codObra != null && !this.codObra.equals(other.codObra))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Dominio.Obra[ codObra=" + codObra + " ]";
    }
}
AUTOR:
package Dominio;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "Autor", catalog = "dbTestesRegras", schema = "dbo")

@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Autor.findAll", query = "SELECT a FROM Autor a"),
    @NamedQuery(name = "Autor.findByCodAutor", query = "SELECT a FROM Autor a WHERE a.codAutor = :codAutor"),
    @NamedQuery(name = "Autor.findByNome", query = "SELECT a FROM Autor a WHERE a.nome = :nome")})

public class Autor implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "CodAutor", nullable = false)
    private Integer codAutor;
    @Column(name = "Nome", length = 30)
    private String nome;
    
//Aqui o relacionamento de Autor com Obra:
    //O FetchType.LAZY significa que o conteúdo da super classe será trazido apenas na primeira solicitação.
    @ManyToMany(fetch= FetchType.LAZY) 
    @JoinTable(name="ObraAutor", joinColumns={@JoinColumn(name="CodAutor")},
            inverseJoinColumns={@JoinColumn(name="CodObra")}) 
    @Cascade(CascadeType.ALL)
    private Collection <Obra> obra = new ArrayList<Obra>();

    public Autor() {
    }

    public Autor(Integer codAutor) {
        this.codAutor = codAutor;
    }

    public Integer getCodAutor() {
        return codAutor;
    }

    public void setCodAutor(Integer codAutor) {
        this.codAutor = codAutor;
    }

    public String getNome() {
        return nome;
    }

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

    @XmlTransient
    public Collection<Obra> getObra() {
        return obra;
    }

    public void setObraCollection(Collection<Obra> obra) {
        this.obra = obra;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (codAutor != null ? codAutor.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 Autor)) {
            return false;
        }
        Autor other = (Autor) object;
        if ((this.codAutor == null && other.codAutor != null) || (this.codAutor != null && !this.codAutor.equals(other.codAutor))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Dominio.Autor[ codAutor=" + codAutor + " ]";
    }
}

Alguém pode me ajudar?

5 Respostas

fbl.lucas

Eu faria da seguinte forma, uma tela para cadastro de Obra e uma para Cadastro de Autor.
Na tela de cadastro de Obra você digitaria o nome do autor e clicaria em um botão “Pesquisar” que abriria uma janela com os resultados da pesquisa onde o usuario selecionaria o autor correspondente. Quando ele selecionasse o autor, você iria adicionar ele na lista “autor”(sugestão: coloque no plural) do objeto Obra.

Quanto ao mapeamento, ta errado. Em Obra ficaria assim:

@ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "ObraAutor", joinColumns = { @JoinColumn(name = "CodObra")}, inverseJoinColumns = { @JoinColumn(name = "CodAutor")}) private Collection<Autor> autores = new ArrayList<Autor>();
Autor:

@ManyToMany(fetch= FetchType.LAZY) @JoinTable(name="ObraAutor", joinColumns={@JoinColumn(name="CodAutor")}, inverseJoinColumns={@JoinColumn(name="CodObra")}) private Collection <Obra> obras = new ArrayList<Obra>();
Não é interessante deixar o Cascade pois ao excluir uma obra por exemplo, ele sairia excluindo o autor e vice versa.
E em relacionamento ManyToMany o simples fato de adicionar ou remover itens da lista, ao salvar ou atualizar o objeto que contém a lista, a lista é atualizada no banco

Jackye

Como faria mais ou menos essa adição na coleção?

Veja o anexo, fiz uma janela onde busca todos os autores do banco.
Como faço o evento de adicionar o autor escolhido na tabela da janela de cadastro?
E como faço pra salvar no banco?


fbl.lucas

Então, quando você clicar em “Adicionar Autor” você pegaria o autor selecionado e vai jogando na tabela da outra janela.
Para salvar, quando clicar em salvar você instanciaria um objeto do tipo Obra setaria os dados informados e os autores selecionados.
Depois era só chamar a DAO de Obra e mandar salvar…Não sei como esta o resto do seu código, mas o caminho é esse

Jackye

Olá.

Pra salvar no banco eu fiz assim:
public Livro PrencherCamposLivro(Livro livro) {
        livro.setTitulo(jTextField2.getText());
        livro.setIsbn(Integer.valueOf(jTextField3.getText()));
        livro.setNuExemplar(Integer.valueOf(jTextField4.getText()));
        
        return livro;
    }

    public void cadastrarLivro() {
        // fazendo a validação dos dados
        if ((jTextField2.getText().isEmpty()) || (jTextField3.getText().isEmpty()) || (jTextField4.getText().isEmpty())) {
            JOptionPane.showMessageDialog(null, "Os campos não podem retornar vazios");
        } else {
             LivroDAO.fabricaLivroDAO().salvar(PrencherCamposLivro(new Livro()));
            JOptionPane.showMessageDialog(null, "Obra inserida com sucesso! ");
            limparCamposLivro();
        }
    }

Chamo o método cadastrarLivro() lá no botão salvar.

Minha dúvida é como pegar os dados da tabela para salvar. E como selecionar o autor lá na outra janela e add na janela de cadastro.

Tem como me mostrar um exemplo? Por favor!

Jackye
Eu tentei fazer assim pra gravar o collection:
public Livro PrencherCamposLivro(Livro livro) {
        livro.setTitulo(jTextField2.getText());
        livro.setIsbn(Integer.valueOf(jTextField3.getText()));
        livro.setNuExemplar(Integer.valueOf(jTextField4.getText()));

      //Tentei dessa forma, mas não funciona.
        List<Autor> autores = new ArrayList<Autor>();
         TbAutores = (DefaultTableModel) jTable1.getModel();
         jTable1.getRowCount();
        livro.setAutorCollection(autores);

        return livro;
    }

Na janela de pesquisa de autor, como faço para referenciar a chamada do autor na tabela de cadastro de obra?

Criado 16 de fevereiro de 2012
Ultima resposta 17 de fev. de 2012
Respostas 5
Participantes 2