Dúvida: Mapeamento Hibernate <key-many-to-one> recupera objeto Nullo (RESOLVIDO)

Pessoal, estou tentando fazer o mapeamento abaixo, porém está sendo retornado objetos com valor NULL. Alguem consegue me ajudar ?

Mapeamento:

&lt;hibernate-mapping&gt;
&lt;class name="modelo.Integrante" table="integrante"&gt;
 
 &lt;composite-id class="modelo.Integrante"&gt;
	 &lt;key-many-to-one class="modelo.Grupo" column="id_grupo" lazy="false" name="grupo"/&gt;
	 &lt;key-many-to-one class="modelo.Funcionario" column="id_func" lazy="false" name="funcionario"/&gt;
 &lt;/composite-id&gt;

// OBS: Funciona se eu não utilizar como chave. Assim, por exemplo: &lt;many-to-one class="modelo.Grupo" column="id_grupo" lazy="false" name="grupo" outer-join="true"/&gt;
// Me parece que o outer-join="true" é a diferença, porém não consigo colocá-lo no key-many-to-onte.

&lt;/class&gt;

&lt;/hibernate-mapping&gt;

Modelo:


public class Integrante implements Serializable
{
	private static final long serialVersionUID = 1L;
	
	private Grupo grupo;
	private Funcionario funcionario;
	
	public Integrante(){}
	
	public Integrante(Grupo grupo, Funcionario funcionario)
	{
		this.grupo = grupo;
		this.funcionario = funcionario;
	}

               // Gets e Sets

Po ninguém tem idéia ???

não tenho ideia com xml, se quiser alguma solução com annotations, posso ate tentar ajudar…

Cara, na minha atual situação aceito sua solução com annotations. Nem o meu professor de java com 6 certificações conseguiu me ajudar com esse mapeamento !! Não sei mais oq faço.

Como ficaria com annotations ? Posso usar annotation só em uma classe e o mapeamento nas demais?

[quote=ataufo]Cara, na minha atual situação aceito sua solução com annotations. Nem o meu professor de java com 6 certificações conseguiu me ajudar com esse mapeamento !! Não sei mais oq faço.

Como ficaria com annotations ? Posso usar annotation só em uma classe e o mapeamento nas demais?[/quote]
Certificações não implicam em conhecimento com Hibernate…

O mapeamento que é feito com annotation pode ser feito tb com xml, eu so não sei faze-los com xml, alem de achar annotation muito melhor

com annotation ? ta abaixo… mas primeiros algumas observações importantes…

[color=red][size=18]leia com calma e atenção o código, ele ta bem comentado, e explicando o pq de quase tudo[/size][/color]
Se não entender algo da um toque

Grupo e Funcionario, devem definir corretamente equals e hashCode, assim como toda classe java o deve fazer.

como Integrante usa um Chave Composta, IntegrantePK é uma chave dessas, e esta bem definda, e como é um ID, não tem métodos sets, pois IDs de um tabela nunca são alterados eles são parametros fixos, que definem a integridade do registro, e por isso seus campos são defindos como final, pois eles nunca são alterados, ao constrario de uma chave com estrategia de Auto_incrimento, onde seu valor só aparece no memento da persistencia, um ID composto tem seu valor conhecido defindo desde o momento de sua criação, visto que ele é enviado pelo usuario…

Note porem, que os IDs de Grupo e Funcionário não precisam ser conhecidos para criar o objeto, porem suas instancias precisam existir e serem enviadas para criar o objeto Integrante…

Obs.: se precisar definir as formas de cascatas com Grupo e FUncionario a partir de Integrante, vc pode definir em @ManyToOne, de cada uma das propriedade e assim, definir por exemplo, que ao persitir um Integrante, que automaticamente seus Grupo e Funcionario sejam persistidos / atualizados

Duvida quanto a equals e hashCode ? de pq e como implementar ? => http://java-i9se.blogspot.com/2009/04/igualdade-em-java-equals-e-hashcode.html

Abaixo seguem as 2 classes mapeadas

1 - IntegrantePK.java: é uma classe Embedable, e portanto pode ser usado como um atributo de outra classe, e esta classe é que define a Chave Primaria composta por Grupo e Funcionario, note que esta classe não é uma entidade, é apenas um propriedade.
2 - Integrante.java: é a entidade propriamente dita, ela usa como ID a classe IntegrantePK, e vc deve mapear os outros atributos da tabela nesta entidade…

[code]@Embedable
public class IntegrantePK implements Serializable {
/**
* Um vez defino o Grupo ele nunca será alterado, portanto ele é defindo como final.
* Isso ocorre pq IDs nunca devem ser alterados.

*

* Obs.: O hibernate vai sobrescrever os método caso precise criar um IntegrantePK,
* e getGrupo estara seguramente enviando dados não nulos direto do banco.
*/
@ManyToOne
@JoinColumn(name=“id_grupo”)
private final Grupo grupo;

/**
 * Um vez defino o Funcionario ele nunca será alterado, portanto ele é defindo como final.
 * Isso ocorre pq IDs nunca devem ser alterados.<BR>
 * <BR>
 * Obs.: O hibernate vai sobrescrever os método caso precise criar um IntegrantePK, 
 * e getFuncionario estara seguramente enviando dados não nulos direto do banco.
 */
@ManyToOne
@JoinColumn(name="id_func")
private final Funcionario funcionario;   

/**
 * Não deve ser usado nunca, note que mesmo a implementação setando grupo e funcionario null
 * que isso não fará diferença, pois só quem usará esse Construtor é o Hibernate e este já
 * sobrescreve os métodos getGrupo() e getFuncionario() e portanto os valores das propriedades
 * desta sub-classe é indiferente...
 * @deprecated Construtor só existe para o hibernate poder instanciar
 *             não deve ser usado no projeto
 */
@Deprecated
protected IntegrantePK(){grupo = null; funcionario = null;} //visibilidade protected e @Deprecated


public IntegrantePK(Grupo grupo, Funcionario funcionario) {
    if (grupo == null || funcionario == null)
         throw new IllegalArgumentException("Grupo e Funcionário não pode ser nulos");
    this.grupo = grupo;
    this.funcionario = funcionario;
}

public Grupo getGrupo() {
   assert(grupo != null);
   return grupo; 
}
public Funcionario getFuncionario {
   assert(grupo != null);
   return funcionario; 
}

//é importante que não existe métodos "set"s pois é um ID e ids não são alterados.

/**
* Dois IDs serão iguais, quando seu funcionario e grupo forem iguais.
/
public @Override boolean equals(Object o) {
return o instance IntegrantePK && equals((IntegrantePK)o);
}
/
*
* método interno, de teste de igualdade, other nunca deve ser enviado como null
* para não dar erro
* @param other o outro IntegrantePK que nunca poderá ser enviado como null.
*/
private boolean equals(IntegantePK other) {
assert(other != null);
return getGrupo().equals(other.getGrupo()) && getFuncionario().equals(other.getFuncionario());
}

public @Override int hashCode() {
int hash = 3;
hash += 11getGrupo().hashCode();
hash += 11
getFuncionario().hashCode();
return hash;
}
}[/code]

[code]@Entity
//@Table(nome=“digiteOnomeAqui”) //descomente e edit o comentário caso precise definir o nome da tabela
public class Integrante implements Serializable {
/**
* É final, pois é um ID composto, que deve ser definido ao se criar uma instancia
* a partir de um Grupo e um Funcionario.
*/
@EmbeddedId
private final IntegrantePK id;

/**
 * Não deve ser usado nunca, note que mesmo a implementação setando id null
 * que isso não fará diferença, pois só quem usará esse Construtor é o Hibernate e este já
 * sobrescreve o método getId() e portanto os valores das propriedades desta sub-classe
 * é indiferente...
 * @deprecated Construtor só existe para o hibernate poder instanciar
 *             não deve ser usado no projeto
 */

@Deprecated
protected Integrante() {id = null;}

public Integrante(IntegrantePK id) {
this.id = id;
}

public Inegrante(Grupo grupo, Funcionario funcionario) {
this(new IntegrantePK(grupo,funcionario));
}

/**
* Retorna o ID do integrante, composto por um Grupo e um Funcionario.
* É seguro que o ID nunca será null, pois este é defindo ao criar a classe.
*/
public IntegrantePK getId() {
assert(id != null);
return id;
}

public Grupo getGrupo() {
return getId().getGrupo();
}

public Funcionario getFuncionario() {
return getId().getFuncionario();
}

//mais uma vez, é importante que os métodos acima não tenham "set"s
//pois ele fazem parte do ID que é construido junto com o objeto, e configurando
//no momento da construção da instancia.

/**
* Dois Integrantes serão iguais se, e somente se, seus IDs forem iguais.
* @see IntegrantePK#equals(Object)
/
public @Override boolean equals(Object o) {
return o instanceof Integrante && equals((Integrante)o);
}
/
*
* método interno, de teste de igualdade, other nunca deve ser enviado como null
* para não dar erro
* @param other o outro Integrante que nunca poderá ser enviado como null.
*/
private boolean equals(Integrante other) {
assert(other != null);
return getId().equals(other.getId());
}

public @Override int hashCode() {
return getId().hashCode();
}
}[/code]

Cara, muito obrigado !! Mas desculpe a ignorancia, eu devo importar alguma coisa para as annotations funcionarem ? Pois tentei usar e não consegui.

Abraço.

Sim, deve importar o pacote

javax.persistence.*;

se vc nao tiver ele nos seus arquivos pode procurar na internet por EJB3-Persistence que vai acabar encontrando, ou pelo pacote de JPA, fora isso vc deve ter o pacote do hibernate q da suporte a Annotations

IDE como Netbeans, cria projetos de JPA ja com esses pacotes integrados e montados facilmente…

Consegui fazer o import, mas ele reclamou da falta dos SETs: org.hibernate.PropertyNotFoundException: Could not find a setter for property grupo in class modelo.Integrante

cola aki, o código exato que vc usou na sua entidade… q gerou esse erro

ops post duplicado

Tae

package modelo;

import java.io.Serializable;
import javax.persistence.*;

@Entity   
//@Table(nome="digiteOnomeAqui") //descomente e edit o comentário caso precise definir o nome da tabela   
public class Integrante implements Serializable {   
 
	private static final long serialVersionUID = 1L;
/**  
  * É final, pois é um ID composto, que deve ser definido ao se criar uma instancia  
  * a partir de um Grupo e um Funcionario.  
  */   
 @EmbeddedId   
 private final IntegrantePK id;   
   
  /**  
   * Não deve ser usado nunca, note que mesmo a implementação setando id null  
   * que isso não fará diferença, pois só quem usará esse Construtor é o Hibernate e este já  
   * sobrescreve o método getId() e portanto os valores das propriedades desta sub-classe  
   * é indiferente...  
   * @deprecated Construtor só existe para o hibernate poder instanciar  
   *             não deve ser usado no projeto  
   */   
 @Deprecated   
 protected Integrante() {id = null;}   
   
 public Integrante(IntegrantePK id) {   
    this.id = id;   
 }   

 public Integrante(Grupo grupo, Funcionario funcionario) {   
    this(new IntegrantePK(grupo,funcionario));   
 }   
   
 /**  
  * Retorna o ID do integrante, composto por um Grupo e um Funcionario.  
  * É seguro que o ID nunca será null, pois este é defindo ao criar a classe.  
  */   
 public IntegrantePK getId() {   
    assert(id != null);   
    return id;   
 }   

 public Grupo getGrupo() {   
    return getId().getGrupo();   
 }   

 public Funcionario getFuncionario() {   
    return getId().getFuncionario();   
 }   
 

 //mais uma vez, é importante que os métodos acima não tenham "set"s   
 //pois ele fazem parte do ID que é construido junto com o objeto, e configurando   
 //no momento da construção da instancia.   

 /**  
  * Dois Integrantes serão iguais se, e somente se, seus IDs forem iguais.  
  * @see IntegrantePK#equals(Object)  
  */   
 public @Override boolean equals(Object o) {   
    return o instanceof Integrante && equals((Integrante)o);   
 }   
 /**  
  * método interno, de teste de igualdade, other nunca deve ser enviado como null  
  * para não dar erro  
  * @param other o outro Integrante que nunca poderá ser enviado como null.  
  */   
 private boolean equals(Integrante other) {   
    assert(other != null);   
    return getId().equals(other.getId());   
 }   
   
 public @Override int hashCode() {   
    return getId().hashCode();   
 }   
}  
package modelo;

import java.io.Serializable;
import javax.persistence.*;

@Embeddable   
public class IntegrantePK implements Serializable {   

	private static final long serialVersionUID = 1L;

	/**  
     * Um vez defino o Grupo ele nunca será alterado, portanto ele é defindo como final.  
     * Isso ocorre pq IDs nunca devem ser alterados.<BR>  
     * <BR>  
     * Obs.: O hibernate vai sobrescrever os método caso precise criar um IntegrantePK,  
     * e getGrupo estara seguramente enviando dados não nulos direto do banco.  
     */   
    @ManyToOne   
    @JoinColumn(name="id_grupo")   
    private final Grupo grupo;   
  
    /**  
     * Um vez defino o Funcionario ele nunca será alterado, portanto ele é defindo como final.  
     * Isso ocorre pq IDs nunca devem ser alterados.<BR>  
     * <BR>  
     * Obs.: O hibernate vai sobrescrever os método caso precise criar um IntegrantePK,  
     * e getFuncionario estara seguramente enviando dados não nulos direto do banco.  
     */   
    @ManyToOne   
    @JoinColumn(name="id_func")   
    private final Funcionario funcionario;     
       
    /**  
     * Não deve ser usado nunca, note que mesmo a implementação setando grupo e funcionario null  
     * que isso não fará diferença, pois só quem usará esse Construtor é o Hibernate e este já  
     * sobrescreve os métodos getGrupo() e getFuncionario() e portanto os valores das propriedades  
     * desta sub-classe é indiferente...  
     * @deprecated Construtor só existe para o hibernate poder instanciar  
     *             não deve ser usado no projeto  
     */   
    @Deprecated   
    protected IntegrantePK(){grupo = null; funcionario = null;} //visibilidade protected e @Deprecated   
       
       
    public IntegrantePK(Grupo grupo, Funcionario funcionario) {   
        if (grupo == null || funcionario == null)   
             throw new IllegalArgumentException("Grupo e Funcionário não pode ser nulos");   
        this.grupo = grupo;   
        this.funcionario = funcionario;   
    }   
  
    public Grupo getGrupo() {   
       assert(grupo != null);   
       return grupo;   
    }   
    public Funcionario getFuncionario() {   
       assert(grupo != null);   
       return funcionario;   
    }   
       
    //é importante que não existe métodos "set"s pois é um ID e ids não são alterados.   
     
   /**  
    * Dois IDs serão iguais, quando seu funcionario e grupo forem iguais.  
    */   
   public @Override boolean equals(Object o) {   
      return o instanceof IntegrantePK && equals((IntegrantePK)o);   
   }   
   /**  
    * método interno, de teste de igualdade, other nunca deve ser enviado como null  
    * para não dar erro  
    * @param other o outro IntegrantePK que nunca poderá ser enviado como null.  
    */   
   private boolean equals(IntegrantePK other) {   
      assert(other != null);   
      return getGrupo().equals(other.getGrupo()) && getFuncionario().equals(other.getFuncionario());   
   }   
     
   public @Override int hashCode() {   
      int hash = 3;   
      hash += 11*getGrupo().hashCode();   
      hash += 11*getFuncionario().hashCode();   
      return hash;   
   }   
}  

estranho, pq no meufunciona… o.O … coloca entaum os metodos sets… mas deixa eles private… c ainda reclamar sobe o nivel de acesso para protected… mais n poem public

é realmente não deu: org.hibernate.PropertyAccessException: Exception occurred inside setter of modelo.Integrante.grupo

Pessoal, resolvi o problema simplismente inserindo mapped=“true” no composite-id. Segue abaixo:

&lt;hibernate-mapping&gt;

&lt;class name="modelo.Integrante" table="integrante"&gt;
 
 &lt;composite-id mapped="true" class="modelo.Integrante"&gt;
	 &lt;key-many-to-one class="modelo.Grupo" column="id_grupo" lazy="false" name="grupo"/&gt;
	 &lt;key-many-to-one class="modelo.Funcionario" column="id_func" lazy="false" name="funcionario"/&gt;
 &lt;/composite-id&gt;

&lt;/class&gt;

&lt;/hibernate-mapping&gt;