Como salvar as associações Hibernate?[Resolvido]

13 respostas
S

Pessoal,

Estava eu aqui “brincando” com o Hibernate mas ai surgiu uma dúvida.

Tenho 2 tabelas com as seguintes associações:

Tabela Grupos

@Table(name = "Grupos", catalog = "database_bgp")
public class Grupos implements java.io.Serializable {

	// Fields
	@Id
	@Column(name = "idGrupos", unique = true, nullable = false)
	private Integer idGrupos;
	
	@Column(name = "nome", length = 45)	
	private String nome;
	
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "grupos")
	private Set<Participantes> participanteses = new HashSet<Participantes>(0);

	// Constructors

	/** default constructor */
	public Grupos() {
	}
	
	//get and set ...

Tabela Participantes:

@Entity
@Table(name = "Participantes", catalog = "database_bgp")
public class Participantes implements java.io.Serializable {

	// Fields

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "idParticipantes", unique = true, nullable = false)
	private Integer idParticipantes;
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "Grupos_idGrupos")
	private Grupos grupos;
	
	@Column(name = "nome", length = 95)
	private String nome;
	
	@Column(name = "email", length = 65)
	private String email;
	
	@Column(name = "cpf", length = 14)
	private String cpf;

	/** default constructor */
	public Participantes() {
	}
	
	
	//get and set ...

Na hora de eu salvar esta associação estou fazendo o seguinte:

Session sessao = SessionFactory.getSession();
		Transaction tx = sessao.beginTransaction();

		Grupos grupos = new Grupos();
		Participantes participantes = new Participantes();
		
		participantes.setNome("Nome Qualquer");
		participantes.setEmail("[email removido]");
		participantes.setCpf("xxx.xxx.xxx-xx");
		
		grupos.setNome("Xique Mill");
		grupos.getParticipanteses().add(participantes);

		sessao.save(participantes);	
		
		tx.commit();
		sessao.close();

A classe participantes é salvo normalmente, porém o grupo não …

Como eu faço para persistir todas as informações? :shock:

Grato
:lol:

13 Respostas

M

cascade = CascadeType.ALL

S

Mas já atribuido na classe grupos …

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "grupos")   
    private Set<Participantes> participanteses = new HashSet<Participantes>(0);

Tenho que atribuir na classe participantes?

:frowning:

M
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)  
@JoinColumn(name = "Grupos_idGrupos")  
private Grupos grupos;

Depende de onde você está salvando, se você quer salvar um participante e ele também salvar os grupos é como descrevi a cima.
se você quer salvar um grupo de salvar todos os participantes é como já está no seu código.
se você quer salver dos dois jeitos em momentos diferentes, bota cascade nos dois.

S

Engraçado que eu declarei como você indicou …

Mesmo assim … o participante é salvo com sucesso, porem o grupo não é salvo…

Que coisa louca!!

:shock:

Mais alguma sugestão?
:smiley:

L

1° não mapei relacionamentos 1-N ... isso é meu conselho, do fundo do coração... isso da margem a erros, inclusive esse que você colocou...

Caso deseje continuar mapeando seu 1-N veja onde faltou código...
seu código esta faltando um pequeno trecho, mais esssencial para o entendimento...

Session sessao = SessionFactory.getSession();  
Transaction tx = sessao.beginTransaction();  
  
Grupos grupos = new Grupos();  
Participantes participantes = new Participantes();  
  
participantes.setNome(&quot;Nome Qualquer&quot;);  
participantes.setEmail(&quot;[email removido]&quot;);  
participantes.setCpf(&quot;xxx.xxx.xxx-xx&quot;);  
participantes.setGrupos(grupos); //&lt;&lt;==== VC PRECISA SETAR O GRUPO!
  
grupos.setNome(&quot;Xique Mill&quot;);  
grupos.getParticipanteses().add(participantes);  // &lt;=== ISSO AQUI NÃO SETA O GRUPO SOZINHO
  
sessao.save(participantes);   
  
tx.commit();  
sessao.close();

se realmente for continuar usando essa abordagem... aconselho fazer um método em grupos, desta forma

public class Grupos implements java.io.Serializable { //....
   boolean addParticipante(Participante p) {
     if (p != null) {
        p.setGrupos(this);
        return getParticipantes().add(p);
     } else
        return false;
   }
S

Obrigado pelo sugestão …

Mas qual seria a forma de “setar corretamento o grupo” …

Como estou começando agora com Hibernate, tudo que acho é sobre mapeamento, mapeamento …

:cry:

Utilizei o método que você sugeriu … mas agora está lançando o seguinte erro.

ids for this class must be manually assigned before calling save()

O mesmo erro se eu tentasse utilizar:

sessao.save(grupos);

:roll:

L

esse é o perigoso e problematico mundo dos relacionamentos 1-N

o.O

ele tenta fazer cascatas, principalmente em inserts, e vai tentar associar um lado ao outro… porem na associação o ID ainda não existe, e acaba que ele não consegue fazer…

Porem acredito que quando vc usa apenas

session.save(grupos) … não deva dar problema, pois ele vai persistir primeiro o grupo, e em cascata vai persitir os participantes, agora como ID do grupo ja existente…

A outra abordagem existente, é sem os mapeamentes Bilaterais, assim, vc persite em separado…

session.save(grupo); //grupo não vai ter 1-N com participantes
session.save(participante); //agora ele salva o particpante, onde o ID do grupo ja vai estar ajustado…

vc perde a comodidade do grupo.getParticipantes(), mas fica mais facil de usar

P

eu sou da opiniao do lavieri tambem!

S

Para dar um feedback!!

Obrigado Lavieri e Paulo …

Consegui fazer o “troço” funcionar …

Para ajudar a comunidade fica aqui meu código:

Entidade Grupos

@Entity
@Table(name = "Grupos", catalog = "database_bgp")
public class Grupos implements java.io.Serializable {

	// Fields

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "idGrupos", unique = true, nullable = false)
	private Integer idGrupos;
	
	@Column(name = "nome", length = 45)
	private String nome;
	
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "grupos")
	private Collection<Participantes> participantes;

	// Constructor, get and set

Entidade Participantes

@Entity
@Table(name = "Participantes", catalog = "database_bgp")
public class Participantes implements java.io.Serializable {

	// Fields
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "idParticipantes", unique = true, nullable = false)
	private Integer idParticipantes;
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "idGrupos")
	private Grupos grupos;
	
	@Column(name = "nome", length = 95)
	private String nome;
	
	@Column(name = "email", length = 65)
	private String email;
	
	@Column(name = "cpf", length = 14)

	// Constructor, get and set

Para fazer as inserções e associações eu fiz um seguinte:

Session sf = SessionFactory.getSession();
		
		Grupos grupos = new Grupos();
		grupos.setNome("Stratovarius");
		
		Participantes part = new Participantes();
		part.setNome("Fabiano Fernandes");
		part.setCpf("xxx.xxx.xxx-xx");
		part.setEmail("[email removido]");
		part.setGrupos(grupos);
			
		grupos.setParticipantes(new HashSet<Participantes>());
		grupos.getParticipantes().add(part);
		
		
		Transaction tx = sf.beginTransaction();
		sf.save(grupos);
		tx.commit();
		sf.close();

Valeww
Muito obrigado gente
:smiley:

F

Galera primeiramente boa noite à todos.

Me desculpem por postar em um tópico marcado como RESOLVIDO, pois estou com dúvidas referentes ao mapeamento do seguinte cenário:

-----------                -----------------               ---------------  
| Aluno   |                |     Reserva     |             |   Livro      |  
-----------                -----------------               ---------------  
| idAluno | <------------->| idReserva - PK  | <---------->| idLivro      |  
|         |                | idAluno -FK     |             |              |  
-----------                | idLivro -FK     |              ---------------  
                           | dtLocacao       |    
                           -------------------

Já tem alguns meses que travei nessa parte do sistema :cry:

Tenho as classes Aluno e Livro populadas no Banco, daí gostaria fazer a relação com essa tabela associativa Reserva mais ou menos assim:

---------------- ---------- ---------- -------------
 |  idReserva    | idAluno | idLivro  |  dtLocacao  |
 ---------------- ---------- ---------- -------------           
 |     1         |     1   |     5    |  2012-08-18 |
 |     2         |     1   |     2    |  2012-08-18 |
 |     3         |     1   |     8    |  2012-08-18 |
 --------------- ----------- ------------------------

Att,

Fred

W

Bota as classes que você mapeou fredye, o que tu já fez pra podermos sugerir alguma coisa.

F

Opa claro.

Classe Aluno

@Entity
@Table(name = "aluno", catalog = "baselibrus")
public class Aluno implements java.io.Serializable {

	private Integer idAluno;
	private List<Livro> livros;
	
   
    @Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "idAluno", unique = true, nullable = false)
	public Integer getIdAluno() {
		return idAluno;
	}

	public void setIdAluno(Integer idAluno) {
		this.idAluno = idAluno;
	}

        
    @ManyToMany
	@JoinTable(name = "reserva",
	joinColumns =  @JoinColumn( name = "idAluno"),
    inverseJoinColumns = @JoinColumn(name = "idLivro") )
	public List<Livro> getLivros() {
		return livros;
	}

	public void setLivros(List<Livro> livros) {
		this.livros = livros;
	}
}

Classe Reserva

@Entity
@Table(name = "reserva", catalog = "baselibrus")
public class Reserva implements java.io.Serializable {

	private Integer idReserva;
	private Aluno aluno;
	private Livro livro;
	private Date dtLocacao;
	
    @Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idReserva", unique = true, nullable = false)
	public Integer getIdReserva() {
		return this.idReserva;
	}

	public void setIdReserva(Integer idReserva) {
		this.idReserva = idReserva;
	}

	
	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name="idAluno", insertable = false, updatable = false)
	public Aluno getAluno() {
		return aluno;
	}

	public void setAluno(Aluno aluno) {
		this.aluno = aluno;
	}
	
	
	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name="idLivro", insertable = false, updatable = false)
	public Livro getLivro() {
		return livro;
	}

	public void setLivro(Livro livro) {
		this.livro = livro;
	}
	
	
	@Temporal(TemporalType.DATE)
	@Column(name = "dtLocacao", length = 10)
	public Date getDtLocacao() {
		return this.dtLocacao;
	}

	
	public void setDtLocacao(Date dtLocacao) {
		this.dtLocacao = dtLocacao;
	}
	
	
}

Classe Livro

@Entity
@Table(name = "livro", catalog = "baselibrus")
public class Livro implements java.io.Serializable {

	private Integer idLivro;
	
    @Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "idLivro", unique = true, nullable = false)
	public Integer getIdLivro() {
		return idLivro;
	}

	public void setIdLivro(Integer idLivro) {
		this.idLivro = idLivro;
	}

}

wagnerfrancisco obrigado pela atenção.

Att,

Fred

G

Tentando responder o colega Fred, peço desculpas também por responder um tópico marcado como resolvido, mas como ele ficou sem resposta…

-Como temos uma relação N-N (um aluno pode reservar muitos livros e vice-versa um livro podeSer reservado por muitos alunos),;
-vendo pela modelagem entidade-relacional reserva seria uma relação, que no diagrama resultaria em uma outra tabela com as chaves primárias compostas pelas chaves estrangeiras das outras duas tabelas (fora o surrogate da própria Reserva), até ai tudo bem;

Mas como fazer duas anotações no hibernate de chave primaria?

@Id private Aluno aluno; @Id private Livro livro;

Acho que assim não funciona. Então o que você tem que fazer é criar outra classe, declarar os atributos mapeados e dizer que essa classe pode ser usada como um Id usando a anotação @Embeddable. Depois na classe propriamente dita Reserva, o Id passará a ser aquela outra classe junto com a anotação @EmbeddedId no atributo .
Seria mais ou menos o seguinte:

@Embeddable
public class ReservaId implements java.io.Serializable {  
    @ManyToOne
    private Aluno aluno;  
   @ManyToOne
    private Livro livro; 

//getter e setters 
}

//Na classe Reserva
@Entity
public class Reserva{
    @EmbeddedId
    private ReservaId id;

//getters e setters
}

//Na hora de salvar eu faria isso
public void salvaReserva(Aluno a, List<Livro> livros){
   for(Livro l:livros){
    Reserva r = new Reserva();
    reserva.getId.setAluno(a);// Como o aluno seria constante então precisamos somente de um
   reserva.getId.setLivro(l);
    ...
    session.save()
   ....
  }
}

Lembrando que você teria que remover as relações diretas de Aluno em Livro e Livro em Aluno, agora a Classe Reserva faz a intermediação dos dados

//na classe livro
@OneToMany(mappedBy="id.livro")
private Reserva reserva;

//na classe aluno
@OneToMany(mappedBy="id.aluno")
private Reserva reserva;

Espero ter ajudado, e a resposta está super aberta para correções e críticas.

Criado 11 de agosto de 2009
Ultima resposta 3 de out. de 2012
Respostas 13
Participantes 7