Hibernate Annotation- Chave composta

Boa tarde pessoal,

Estou com um problema no mapeamento de duas entidades onde preciso utiliza uma chave composta.

Realizei varios teste utilizando exemplos já postados porém até agora não consegui resolver: abaixo links pesquisados:
http://thiagoprocaci.blogspot.com/2009/04/mapeamento-objeto-relacional-com.html
http://www.guj.com.br/java/213093-problema-com-persistencia-em-relacionamento-n–m

As entidades estão configuradas da seguinte forma:

Entidade Regra:

@Entity
@Table(name="regra")
public class Regra implements Serializable{
        private Integer cod_regra;
        private Collection<RegraProcedimento> cod_procedimento;

	@OneToMany(fetch=FetchType.LAZY)
	@Cascade(value={org.hibernate.annotations.CascadeType.ALL})
	@OrderBy(clause = "codigo")
	@JoinColumn(name="cod_regra")
	public Collection<RegraProcedimento> getCod_procedimento() {
		return cod_procedimento;
	}
	public void setCod_procedimento(Collection<RegraProcedimento> cod_procedimento) {
		this.cod_procedimento = cod_procedimento;
	}


//........continua..........//
}

Entidade RegraProcedimento:

public class RegraProcedimento implements Serializable {
	private Integer codigo; //Sequencial
	private Integer cod_procedimento; //Recebe números aleatórios
	private Regra regra; //código da entidade acima


        //bi-direcionalidade
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name="cod_regra",nullable = false, insertable = false, updatable = false)
	public Regra getRegra() {
		return regra;
	}
	public void setRegra(Regra regra) {
		this.regra = regra;
	}


       //getters and setters

//........continua..........//
}

A entidade RegraProcedimento terá que persistir o código da entidade Regra(foreing key) e o atriburo cod_procedimento o qual os dois serão uma chave composta da entidade RegraProcedimento, ou seja, a chave composta será a foreing key juntamente com o campo da própria tabela.

Abaixo o código que desenvolvi conforme links acima porém não está funcionando:

package com.br.gr.model;

import java.io.Serializable;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;



@Entity
@Table(name="regra_procedimento")
public class RegraProcedimento implements Serializable {
	private Integer codigo;
	private Integer cod_procedimento;
	private Regra regra;
	private RegraProcedimentoKey codRegra_codProcedimento;
		
	public RegraProcedimento(){}
	public RegraProcedimento (Regra regra, Integer cod_procedimento){
		this.codRegra_codProcedimento = new RegraProcedimentoKey();
		this.codRegra_codProcedimento.setCod_regra(regra.getCod_regra());
		this.codRegra_codProcedimento.setCod_procedimento(cod_procedimento);
		this.regra = regra;
		this.cod_procedimento = cod_procedimento;
	}

	public Integer getCodigo() {
		return codigo;
	}
	public void setCodigo(Integer codigo) {
		this.codigo = codigo;
	}
	
	@Column(nullable = false, insertable = false, updatable = false)
	public Integer getCod_procedimento() {
		return cod_procedimento;
	}
	public void setCod_procedimento(Integer cod_procedimento) {
		this.cod_procedimento = cod_procedimento;
	}
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name="cod_regra",nullable = false, insertable = false, updatable = false)
	public Regra getRegra() {
		return regra;
	}
	public void setRegra(Regra regra) {
		this.regra = regra;
	}


	@EmbeddedId
	public RegraProcedimentoKey getCodRegra_codProcedimento() {
		return codRegra_codProcedimento;
	}
	public void setCodRegra_codProcedimento(
			RegraProcedimentoKey codRegra_codProcedimento) {
		this.codRegra_codProcedimento = codRegra_codProcedimento;
	}


	@Embeddable
	public static class RegraProcedimentoKey implements Serializable{
		private Integer cod_regra;
		private Integer cod_procedimento;

		@Column(name="cod_regra", nullable=false)
		public Integer getCod_regra() {
			return cod_regra;
		}
		public void setCod_regra(Integer cod_regra) {
			this.cod_regra = cod_regra;
		}
		
		@Column(nullable = false)
		public Integer getCod_procedimento() {
			return cod_procedimento;
		}
		public void setCod_procedimento(Integer cod_procedimento) {
			this.cod_procedimento = cod_procedimento;
		}

		@Override  
		public int hashCode() {  
			final int prime = 31;  
			int result = 1;  
			result = prime * result + cod_regra; 
			return result;  
		}  

		@Override  
		public boolean equals(Object obj) {  
			if (this == obj)  
				return true;  
			if (obj == null)  
				return false;  
			if (getClass() != obj.getClass())  
				return false;  
			return true;  
		} 


	}

}

Ocorre o seguinte erro:

Obrigado pela ajuda.

Essa linha:

explica todo o seu problema…

Ok, já havia observado essa mensagem, mas devido os testes constatei que esse código não está nulo. Abaixo irei adicionar o codigo o qual estou realizando os testes.

       //Estou buscando um registro da tabela com todos os campos obrigatórios preenchidos, inclusive cod_regra, observe que o cod_regra = 28
       Session s = HibernateTeste.getSession(false);
       Criteria cr = s.createCriteria(Regra.class);
       cr.add(Restrictions.eq("cod_regra", 28));

       //Cast da retorno da consulta para o objeto em questão.
       Regra regra = (Regra) cr.uniqueResult();

       //Aqui estou utilizando o contrutor criado no código anterior para setar os atributos da classe @Embeddable (para criação da chave primária.
       RegraProcedimento rp = new RegraProcedimento(regra,123);//Contrutor que recebe objeto regra e o código onde será a chave composta.
       rp.setCodigo(1); //número sequencial qualquer.
		
       //Por se tratar de um relacionamento @OneToMany tenho que adicionar o objeto à uma Lista conforme abaixo.
       List<RegraProcedimento> list = new ArrayList<RegraProcedimento>();
       list.add(rp);

       //Adicionado o objeto RegraProcedimento à lista do objeto Regra.
       regra.setCod_procedimento(list);

       //Realizo o merge para nao ocorre problemas de objetos duplicados a Session, mas em produção utilizo saveOrUpdate();
       s.beginTransaction();
       s.merge(regra);
       s.flush();


       //Após isso ocorre o erro o qual postei anteriormente.

Obrigado.

Realizei alteração no mapeamento da Entidade Regra eliminando a Annotation cascade, ai o erro mudou.

Vlw

axo q o problema é esse merge, num sei ao certo!

veja a explicação abaixo:

http://blog.caelum.com.br/entidades-managed-transient-e-detached-no-hibernate-e-jpa/

Luxu,

Pensei isso tbm e alterei para saveOrUpdate();

Tentei salvar a Entidade Regra a qual possui uma lista de RegraProcedimento não deu certo.
Teitei salvar a Entidade RegraProcedimento o qual está mapeada com a Entidade Regra e tbm não deu certo.

Havia me atentado a esse problema tbm mas nada deu certo.

Vlw

qdo vc tenta salvar vc tem q passar um id q esteja cadastrado na outra tabela, e me parece q nessa pesquisa com o criteria essa id 23 não existe dai ele naum axa nd e retorna nada deixando null, saka? debug seu código pra v o q está errando ok?

Não é isso.

A consulta que faço cm critéria é buscando justamente um registro existente para não precisar setar todos os códigos nulos.

Fiz o debug varias vezes, conferi os códigos e todos estão preenchidos, inclusive o cod_regra, o qual o banco informa que está nulo.

Googando eu achei exemplos de chave composta utilizando 2 entidades ou apenas duas chaves simples (String ou Integer), mas não achei exemplo onde a chave composta será o código de uma Entidade(cod_regra) externa e um atributo interno (cod_procedimento).

Ja fiz varios testes e nao sei mais o que fazer…hehehe Tem que rir pra não chorar…kkkkk
Se não conseguir resolver vo procurar outra abordagem e refazer o código.

Vlw