Hibernate, ajuda com chave primária composta

7 respostas
N

Olá, comecei a trabalhar a pouco tempo com Hibernate, li este tópico, mas não consegui obter sucesso.

Meu problema é o seguinte, tenho uma view em postgre, ela junta dados de duas tabelas diferentes Clientes e Funcionários, tenho ela mapeada, porém ocorre que um cliente tem um id e um funcionario tem um id também, até ai tudo bem, porém quando juntam-se as duas tabelas pela view os ids ficam repetidos, exemplo:

Funcionario ID Nome 1 José 2 Carlos 3 João

Cliente ID Nome 1 Paulo 2 Ricardo 3 Felipe

View Contato(Funcionario x Cliente) ID Nome Tipo 1 José Funcionário 2 Carlos Funcionário 3 João Funcionário 1 Paulo Cliente 2 Ricardo Cliente 3 Felipe Cliente

Como o Hibernate está considerando o ID como chave primaria ele está pegando o primeiro nº que aparece da chave e ignorando os demais, no caso acima ele pegaria o José, mas não pegaria o Paulo, pois já existe o ID 1, logo teria que usar uma chave composta com o ID e Tipo, porém não sei como.

Não posso alterar a view, então estava tentando usar uma composite-id, porém como os dados vem da mesma tabela estou me atrapalhando um pouco, pois não achei nenhum exemplo com isso.

Obrigado.

7 Respostas

L

O item 5.1.7 do manual do Hibernate fala sobre composite-id:
http://www.hibernate.org/hib_docs/reference/en/html/mapping.html

Vou tentar arrumar um exemplo pra você.

Abraços.

N

Obrigado, já li essa parte, porém como disse, não consegui, deixei assim:

<class name="Contato" table="viewContato" lazy="false" > <composite-id name="contatoPk" class="ContatoPk"> <key-property name="idContato" column="id_contato" type="java.lang.Integer" /> <key-property name="txtTipoContato" type="java.lang.String" column="txtTipoContato" /> </composite-id> <property.......

L

Bom...

Segue o exemplo que tenho e que funciona perfeitamente em minha aplicação:

Eu tenho uma view que possui uma chave composta entre o id de um usuário e sua chave. Ao invés de possuir as propriedades id e chave a classe usuário possui uma classe que possui estas duas propriedades representando minha chave composta. As classes ficam assim: - Usuario.java
package br.com.xxxxx.model;

import java.util.Date;

public class Usuario  {

	private static final long serialVersionUID = 1L;
	
	private UsuarioPK usuarioPK;
	
	private String email;
	
	private String nome;
	
	public Usuario(){
		this.usuarioPK = new UsuarioPK();
	}
	
	//getters and setters

}
-UsuarioPK.java
package br.com.xxxxx.model;


import java.io.Serializable;

import java.math.BigDecimal;


public class UsuarioPK implements Serializable{

	private static final long serialVersionUID = 1L;
	
	private BigDecimal id;
	
	private String chave;
	
	//getters and setters

}
Dessa forma, o mapeamento da classe Usuario no hibernate deixa de usar o id e passa a usar o composite-id. Segue exemplo: - Usuario.hbm.xml
...
<composite-id name="usuarioPK" class="br.com.xxxxx.model.UsuarioPK">
	<key-property name="id" type="big_decimal">   
		<column name="USUA_ID_USUARIO" sql-type="number(5,0)" />   
	</key-property>   
	<key-property name="chave" type="string" length="4">   
		<column name="USUA_CD_CHAVE" sql-type="char(4)" />   
	</key-property>   
</composite-id>
...
E no mapeamento das classes que fazem referência à classe Usuario: - Solicitacao.xml.hbm
...
<many-to-one
			name="usuarioSolicitante"
			class="br.com.xxxxx.model.Usuario"
			cascade="all"
			lazy="false" 
			insert="false" update="false" > 
	<column name="USUA_ID_USUARIO_SOLICITANTE" sql-type="number(5,0)" />
	<column name="USUA_CD_CHAVE_SOLICITANTE" sql-type="char(4)"/>
</many-to-one>
...
Abaixo, a classe que faz referência à classe Usuario: - Solicitacao.java
package br.com.xxxxx.model;

//imports

public class Solicitacao implements Comparable {

	private static final long serialVersionUID = 1L;

	private String id;
	
	private Usuario usuarioSolicitante;
	
	//getters and settings

}

Enfim...
Isso funcionou muito bem.
Espero que seja útil pra você!

Abraços.

N

Obrigado mesmo, consegui fazer aqui, obrigado mesmo. :slight_smile:

L

Que bom que funcionou!

Abraços.

P

Peço desculppa por me intrometer no post mas estou a tentar construir uma consulta a uma tabela com chave composta e não estou a conseguir, a aplicação devolve o erro:

Missing column: feriasfuncPK in PES.dbo.feriasfunc

onde feriasfuncPK é o objecto da classe que define a chave composta. Parece-me estranho mas acho que o Jboss está a interpreta-lo como um atributo normal ou seja mais uma coluna na tabela.

17:04:46,877 INFO  [TableMetadata] columns: [dias_ferias, dias_suplement, dias_por_gozar, dias_antig, numero, obs, data_login, ano, login, dias_descontados, dias_gozados, rowid, dias_acumulados, dias_idade]
17:04:46,877 WARN  [ServiceController] Problem starting service persistence.units:ear=fFunc-ear.ear,unitName=fFunc
javax.persistence.PersistenceException: [PersistenceUnit: fFunc] Unable to build EntityManagerFactory
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
	...
	at java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.HibernateException: Missing column: feriasfuncPK in PES.dbo.feriasfunc
	at org.hibernate.mapping.Table.validateColumns(Table.java:277)
	...
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
	... 145 more
...

Classe feriasfunc.java

@Entity
public class feriasfunc implements Serializable {
	
	@EmbeddedId
	private FeriasfuncPK feriasfuncPK;
	private Integer rowid;
    private Integer dias_ferias;
    private Integer dias_suplement;
    private Float dias_descontados;
    private Float dias_acumulados;
    private Float dias_gozados;
    private Float dias_por_gozar;
    private String obs;
    private String login;
    private Date data_login;
    private Integer dias_idade;
    private Integer dias_antig;
    
    

    // attribute getters/setters with annotations

    public feriasfunc()
    {
    	this.feriasfuncPK = new FeriasfuncPK();
    }

	/**
	 * @param feriasfuncPK the feriasfuncPK to set
	 */
	public void setFeriasfuncPK(FeriasfuncPK feriasfuncPK) {
		this.feriasfuncPK = feriasfuncPK;
	}

	/**
	 * @return the feriasfuncPK
	 */
	
	
	public FeriasfuncPK getFeriasfuncPK() {
		return feriasfuncPK;
	}
...

classe FeriasfuncPK.java

package org.domain.fFunc.entity;

import java.io.Serializable;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;




public class FeriasfuncPK implements Serializable {
	        
	        //declare composite properties
	        // declare constructor
		
		public Integer numero;
		public Integer ano;
		
		public void setNumero(Integer numero) {
			this.numero = numero;
		}
		
	   
		public Integer getNumero() {
			return numero;
		}
	    
		public void setAno(Integer ano) {
			this.ano = ano;
		}
		
		public  Integer getAno() {
			return ano;
		}

                ....

e por fim o hbm

<hibernate-mapping package="org.domain.fFunc.entity">
 <class catalog="PES" name="feriasfunc" table="feriasfunc">

   <composite-id
        name="feriasfuncPK"
        class="org.domain.fFunc.FeriasfuncPK">              
        <key-property  name="numero" column="numero" type="integer" />
        <key-property name="ano" column="ano" type="integer" />         
   </composite-id>
...

Se poderem ajudar agradeço bastante.

L

Tente utilizar feriasfuncPK.ano e feriasfuncPK.numero dentro de suas consultas.

Abraços.

Criado 6 de outubro de 2008
Ultima resposta 14 de nov. de 2008
Respostas 7
Participantes 3