[hibernate] Problemas com chaves compostas (composite-id)

Tenho a seguinte estrutura no bd:

empresa
emp_res varchar(3) primary key,
emp_des varchar(50)

produto
pr_cod_pro varchar(20) primary key,
pr_emp_res varchar(3) primary key,
pr_des_pro varchar(50)

embalagem
em_cod_emb varchar(3) primary key,
em_emp_res varchar(3) primary key
em_des_emb varchar(30)

produto_embalagem (produto x embalagem)
pe_emp_res varchar(3) primary key,
pe_cod_pro varchar(20) primary key,
pe_cod_emb varchar(3) primary key

Estou criando classes para representar minhas chaves compostas. O meu problema está com a última tabela. Criei uma classe para representar esta chave composta desta maneira:

public class ProdutoEmbalagemPk {
   private Empresa empresa;   //pe_emp_res
   private Produto produto;   //pe_cod_pro
   private Embalagem embalagem;   //pe_cod_emb
   //get's, set's, equals and hashCode method
}

Só que ele acusa o seguinte erro:

net.sf.hibernate.MappingException: Foreign key (produto_embalagem [pe_cod_emb])) must have same number of columns as the referenced primary key (embalagem [em_cod_emb,em_emp_res])
	at net.sf.hibernate.mapping.ForeignKey.setReferencedTable(ForeignKey.java:60)
	at net.sf.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:667)
	at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:761)
	at net.sf.hibern8ide.Hibern8IDE.initialize(Hibern8IDE.java:227)
	at net.sf.hibern8ide.Hibern8IDE.setupUI(Hibern8IDE.java:486)
	at net.sf.hibern8ide.Hibern8IDE.start(Hibern8IDE.java:421)
	at net.sf.hibern8ide.Hibern8IDE.startWith(Hibern8IDE.java:389)
	at br.com.atmtec.dao.hibernate.HibernateConsole.main(HibernateConsole.java:70)

Acredito que o problema está em utilizar objetos que possuem chave composta na composição de outra chave composta. Alguém confirma isso? Se sim, qual a solução para o problema?

bem nao vou saber te ajudar quanto a sua duvida, mais eu tenho uma que voce pode me responder :slight_smile: o pq criar uma classe com as pk ?
estou aprendendo a usar hibernate…e nao tinha visto isso…

Oi Marcelo,

Então… para te responder melhor, precisaria que você colocasse a parte de chave estrangeira do xml de mapeamento, ou se estiver usando XDoclet para mapear (o que diga-se de passagem é muito prático) , as meta-tags para o xDoclet. :wink:

Mas só adiantando, chave composta só dá dor de cabeça! Sentimos muito esse problema implementando em EJB (CMP, para ser mais clara) e a coisa não fica mais fácil quando implementada com hibernate.
A solução que achamos foi usar uma técnica de Dataware House chamada Surrogate Key. Tem seus prós e contras, mas para dizer a verdade, achamos muito mais prós do que contras. :smiley:

A modelagem do seu bd também está um pouco confusa. Ela permite que um produto da empresa X seja embalado pela embalagem da empresa Y, mas só tem uma chave de empresa na relação produdo x empresa.
Se seu sistema tiver que permitir isso, a estrutura da relação teria que ser:

produto_embalagem (produto x embalagem)
pe_emp_res_prod varchar(3) primary key,
pe_cod_pro varchar(20) primary key,
pe_emp_res_emb varchar(3) primary key,
pe_cod_emb varchar(3) primary key

Caso contrário, eu sugeriria a seguinte estrutura para seu bd:

[code]
empresa
emp_res varchar(3) primary key,
emp_des varchar(50)

produto
pr_cod_pro varchar(20) primary key,
pr_des_pro varchar(50)

embalagem
em_cod_emb varchar(3) primary key,
em_des_emb varchar(30)

produto_embalagem (produto x embalagem)
pe_emp_res varchar(3) primary key,
pe_cod_pro varchar(20) primary key,
pe_cod_emb varchar(3) primary key[/code]
Assim a empresa fica dona da relação produto x embalagem

Eu acho que com essas relações você deve chegar a solução do seu problema.

Bom, espero ter ajudado.
Boa sorte! :wink:

Está um pouco estranha a implementação do seu BD, acho que na tabela “Embalagem” você poderia deixar a empresa como uma FK e não PK, assim vc reduziria a carga de chaves na tabela “EmbalagemProduto”.

Agora uma pergunta, vc construiu também uma classe EmbalagemPK? Se não construiu o problema está aí. Se já construiu então tente colocá-la como atributo na classe EmbalagemProdutoPK no lugar da classe Embalagem, talvez funcione.

[quote=smorigo]bem nao vou saber te ajudar quanto a sua duvida, mais eu tenho uma que voce pode me responder :slight_smile: o pq criar uma classe com as pk ?
estou aprendendo a usar hibernate…e nao tinha visto isso…[/quote]
Quando você possui uma tabela com uma chave composta (composite-id) vc deve criar uma classe contendo os dados da chave e mais algumas coisas (hashCode, equals, …). Mais detalhes na documentação do hibernate.

[]'s

Eduardo

Oi gleise, vamos lá tentar esclarecer alguns pontos. Primeiro eu estou utilizando o XDoclet sim, realmente ajuda bastante. Só quero esclarecer que o que postei é um exemplo, a estrutura é muito grande e complexa.

Pois é, tentei mudar a cabeça dos “analistas” mas não teve jeito, não abriram mão de chaves compostas. Eu já sabia que teria um tarefa árdua daqui para frente.

Eu sei, o exemplo é pobre, mas não é isso não. Estamos desenvolvendo um ERP e uma das características é ser multi-empresa. Portanto não vamos permitir produto X tenha embalagem da empresa Y, isto pq usuário da empresa X não enxergará produtos e embalagens da empresa Y.

Oi eduardo,

No post anterior eu esclarecí isto.

Sim, eu tenho EmbalagemPk definida. Posso tentar, porém fica visível que perderei funcionalidades aqui.

Obrigado, se tiverem mais alguma sugestão por favor vcs me dão um alô.

http://forum.hibernate.org/viewtopic.php?t=933808&highlight=compositeid