Em uma tabela, tenho um campo que é chave, e que é da própria tabela, e um outro campo q é chave mas que é foreing key.Os dois formam minha chave composta. Quando eu deixo o campo que é foreing key no mapeamento como apenas <key-property> ele dá certo. Mas eu acho q o correto mesmo seria se ele fosse <key-many-to-one>, já que ele se refere a um campo de outra tabela. Mas quando eu mudo pra este tipo não dá certo…
O que pode estar acontecendo? Qual a forma correta de se usar <key-many-to-one>…os .java e hbm ???
AH e eu nao estou usando annotations e nem o plugin do eclipse…por favor…se puderem me dar exemplos sem os “arrobas”…rs
hibernateXcompositeID
25 Respostas
Não seria algo assim?
<composite-id>
<key-property name="chave" column="chave" />
<key-many-to-one name="estrangeira" class="ClasseEstrangeira" column="estrangeira"/>
</composite-id>
Assim não funciona? Qual o erro?
Assim mesmo que eu estou fazendo.
Será algum erro na implementação da ClasseEstrangeira? Você poderia me dar um exemplo de como fica a ClasseEstrangeiro (VO e DAO) ?
Obrigada!
acho que seria algo assim:
public class ClasseEstrangeira{
private int id;
private String nome;
//get & set
}
public class OutraClasse{
private int id;
private ClasseEstrangeira estrangeira;
private String dado;
}
<class name="ClasseEstrangeira" table="estrangeiras">
<id name="id">
<generator class="native" />
</id>
<property name="nome" />
>
<class name="OutraClasse" table="outras">
<composite-id>
<key-property name="chave" column="chave" />
<key-many-to-one name="estrangeira" class="ClasseEstrangeira" column="estrangeira"/>
</composite-id>
<property name="dado" />
</class>
Qual o erro dá?
Eu estou fazendo exatamente assim!!!
Mas não tem um lance de que, quando usamos composite-ID, tem que ser feita uma classe representando apenas o composite-ID??? Acho que o meu erro está aí…nao estou sabendo fazer certo…
AH! O erro dá na hora em que eu clico no botão Inserir…o JSP que acusa o erro (Tomcat). A mensagem se refere a erro no mapeamento.
Ahh esqueci, as classe que usam composite-id devem ser serializaveis e implementar os metodos equals() e hashCode(). :oops:
Implementa aí…
Eu uso HashSet no caso na ClasseEstrangeira…faço assim:
Set outrasclasses = new HashSet()
//get e set para outrasclasses
Como assim implementar os métodos equals e HashCode?
A ClasseEstrangeira e OutraClasse devem ser serializable???
Veja:
public class ClasseEstrangeira implements Serializable{
private int id;
private String nome;
//get & set
public boolean equals(Object obj){
if(!(obj instaceof ClasseEstrangeira)){
return false;
}
ClasseEstrangeira ce = (ClasseEstrangeira) obj;
return getId()==ce.getId();
}
public int hashCode(){
return Integer.valueOf(getId()).hashCode();
}
}
public class OutraClasse implements Serializable{
private int id;
private ClasseEstrangeira estrangeira;
private String dado;
public boolean equals(Object obj){
if(!(obj instanceof OutraClasse)){
return false;
}
OutraCasse oc = (OutraClasse) obj;
return (getId()==oc.getId()&&getEstrangeira().equals(oc.getEstrangeira());
}
public int hashCode(){
return 37*(Integer.valueOf(getId()).hashCode()+getEstrangeira().hashCode());
}
}
Não sei se as implementações estão totalmente certas não, porque fiz rapido aqui, mas testa aí...
ps.: pra saber mais sobre equals() e hashCode():
eu fiz exatamente o que vc falou.
Mas em OutraClasse…o q eu coloco como o id?
Esta OutraClasse é exatamente a que se refere à tabela com chave composta. Uma das chaves é um timestamp :dt_cadastro…e a outra chave é o id_usuario ( que vem da minha tabela estrangeira (usuario). Como q eu faço neste caso?
E me diga tambem onde eu vou utilizar este equals e hashcode…
Muito obrigada pela atenção dispensada…vc está sendo legal comigo
Nesse caso o que eu chamei de "id" é o seu dt_cadastro, é só substituir...
O metodo equals() você pode usar para saber se dois objetos são iguais...
ex.:
OutraClasse o1 = new OutraClasse();
OutraClasse o2 = new OutraClasse();
if(o1.equals(o2)){
//os objetos são iguais
}else{
//os objetos são diferentes
}
O metodo hashCode() é usado para obter um codigo hash do objeto. E raramente é usado diretamente, quem usa muito isso são as coleções onde você coloca esse objeto, como um HashTable.
Nesse caso você não vai usar esses metodos, quem vai usar é o hibernate...
Mais detalhes em: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
ahhh entendi !!!
só está me dando erro nesta linha:
seria o sinal ==mesmo ???
(getId()==oc.getId()&&getEstrangeira().equals(oc.getEstrangeira());
acho q estou chegando lá…
me diga uma coisa…no DAO como vou fazer para inserir os dados???
É o == mesmo, tente colocar as expressões entre parenteses…
No DAO é só você chamar o metodo save() de uma Session que ele vai salvar seu objeto…
ex.:
OutraClasse oc = new OutraClasse();
//preenche com os dados
Session sessao = sessionFactory.openSession();
Transaction tsct = sessao.beginTransaction();
sessao.save(oc);
tsct.commit();
sessao.close();
concertei os parenteses…rssrrs
o erro agora está dando pq a minha chave Dt_cadastro pe timestamp.
public int hashCode(){
return 37*(Integer.valueOf(getDt_cadastro()).hashCode()+getUsuario().hashCode());
como eu faço no Integer.valueOf(getDt_cadastro() ??? se eu ter um getTime retorna um long e nao int…
My Goooooooddd rssrrs
É só tirar o Integer.valueOf()
ok…agora compilou.
Mas continua me dando o meeesmo erro no JSP…
Como seria a parte de código para eu inserir no banco justamente os campos referentes à chave composta? acho q é isto que está pegando…pq o meu DAO está igualzinho ao que vc mandou. E todo o código q vc me mandou eu implemente nos respectivos VO das classes OutraClasse e ClasseEstrangeira. Eu ainda acho q o q tá pegando é o DAO…
valeu mais uma vez
Qual o erro?
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:848)
Este erro…de tanto apanhar com minhas outras tabelas q nao sao chave composta e q estao todas dando certo, acontece quando existe erro no mapeamento.
Vou almoçar e jah volto…
Existem alguns exemplos em q se existe uma classe para o composite-id…por exemplo uma classe Chave cujo os atributos sao as colunas pk. Já ouviu falar algo sobre? Como eu poderia aplicar o q vc me passou nisto?
Isso não é aplicado a Hibernate, isso é em Entity Bean…
Esse erro que você postou não mostra o erro do Hibernate, pegue o erro completo e coloque aí…
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:848)
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:781)
org.apache.jsp.consulta_005fhist_005fusuario_jsp._jspService(consulta_005fhist_005fusuario_jsp.java:216)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:322)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:291)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)
Não está aparecendo erro nenhum de Hibernate aí não…
Tenta rodar isso fora desse JSP, em outra classe, uma aplicação Standalone, algo assim… pode rodar no debug tambem…
seu eu tiroi o key-many-to-one ele funciona perfeitamente do jeito q eu tinha feito. O tomcat nao reconhece erros de hibernate…por isto dah este erro. Nao adianta eu fazer standalone…o q eu tenho q entregar é JSP…bom…se nao puder me ajudar mais jah agradeco tudo ate agora…
até maiisss
Se você fizer standalone você pode debugar mais facil, ou simplesmente dar um printStackTrace() na exceção pra ver a mensagem… e no log do tomcat aparece o stack trace completo…
Eu entendi o q vc quis dizer…mas não foi preciso …rsrs
Este ocorre toda vez que algo está errado no xml (mapeamento), seja um caracter a mais, uma palavra a mais e q nao deveria estar lá.
Eu resolvi o meu problema, consegui com que minha aplicação reconhecesse um dos meus campos da chave composta como sendo um campo vindo de outra tabela.
Aquele lance de que é preciso uma classe exclusivamente para o composite-id é verdade…senão não funciona meeeesssmo! E aqueles lances dos metodos equals e hashcode eu nao precisei implementar não…mas deixei lá comentado.
Olha só a classe para o composite-id:
/*
- CompositeIDHistUsuario.java
- Created on 18 de Setembro de 2006, 11:03
- To change this template, choose Tools | Template Manager
- and open the template in the editor. */
package vo;
import java.io.Serializable;
public class HistUsuarioPK implements Serializable
{
//campo da classe a ser mapeada mesmo
private java.sql.Timestamp dt_cadastro;
//campo na classe a ser mapeada e que é foreing key, se instancia o objeto
private Usuario usuario;
public java.sql.Timestamp getDt_cadastro() {
return dt_cadastro;
}
public void setDt_cadastro(java.sql.Timestamp dt_cadastro) {
this.dt_cadastro = dt_cadastro;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
}
Este é o trecho no DAO…que era o que eu tinha dúvida:
depois dos comandos abrindo o hibernate e inserindo demais campos
(…)
// Chave Composta
Usuario usuario=new Usuario();
//o id_usuario eu passei como parametro
usuario = (Usuario)sessao.get(Usuario.class, id_usuario);
HistUsuarioPK ch= new HistUsuarioPK();
ch.setDt_cadastro(dt_cadastro);
ch.setUsuario(usuario);
hist_usuario.setChave(ch);
sessao.save(hist_usuario);
transacao.commit();
sessao.close();
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
e a parte do composite Id no mapeamento ficou assim:
<composite-id name=“Chave” class=“HistUsuarioPK”>
<key-property name=“Dt_cadastro” type=“timestamp”>
<column name=“dt_cadastro”/>
</key-property>
<key-many-to-one name="Usuario">
<column name="id_usuario"/>
</key-many-to-one>
</composite-id>
tirei uns atributos do key-many-to-one pq estavam fazendo não dar certo.
BOm colega, é isto. MUITO OBRIGADA PELA ATENÇÃO!!!
AH! o que é classpath é sacanagem pow…foi vc quem colocou isto pra mim? srrssrrs
Maravilha que funcionou…
Mas esse negocio de criar uma classe pra chave da classe é opicional, apesar do pessoal do Hibernate recomenda-la, eu sempre usei sem criar essa classe, mas se no seu caso é melhor assim, otimo então…
Se você precisar consultar no futuro:
http://www.hibernate.org/hib_docs/v3/reference/en/html/mapping.html#mapping-declaration-compositeid
Não, não. Isso é automatico, é baseado na quantidade de mensagens que você tem no forum…