[Meio Resolvido] Chave composta em uma tabela de relacionamento do hibernate

4 respostas
crpablo

Deixa eu explicar bem meu problema... Talvez alguém já tenha passado por isso, ou saiba pelo menos o caminho a seguir...

Explicando....

Eu tenho um bd legado, onde, entre outras, tenho uma tabela USUARIO e uma MAPA o relacionamento dessas tabelas é N:M, ou seja, um USUARIO pode acessar vários mapas e um MAPA pode ser acessado por vários usuarios.
Devido a esse relacionamento, o hibernate criou uma tabela de relacionamento com o nome USUARIO_MAPA, que consta somente duas colunas, USUARIOS_ID e MAPAS_ID, onde é feita a ligação das duas tabelas...

O que eu estou fazendo é o seguinte, todas essas tabelas que tenho no meu bd são mapeadas pelo hibernate por suas classes, as Entitys. Através dessas classes e seus DAOS eu estou serializando o conteúdo das tabelas em arquivos XML. Esses arquivos estão sendo utilizados como uma forma de backup e resturação desse banco, além também da possível troca de SGBD...
Eu serializo em XML e depois desserializo e persisto novamente no BD.

O meu problema é o seguinte, para gerar esse XML, eu precisei criar o entity para a tabela de relacionamento(USUARIO_MAPA) que foi gerada pelo hibernate, porém, essa classe como tem somente dois atributos USUARIOS_ID e MAPAS_ID precisa ter uma coluna @Id. Então se eu deixo somente a coluna USUARIOS_ID com o annotation @Id, não consigo que usuários diferentes tenham acesso ao mesmo mapa... caso altere o annotation para MAPAS_ID, não consigo que um usuário tenha acesso a mais de um mapa...

Segue o cód. dessa class...
import javax.persistence.Entity;
import javax.persistence.Id;

@SuppressWarnings("serial")
@Entity
public class Usuario_Mapa extends CiaEntity {

	@Id
	private long usuario_id;
	private long mapas_id;

	public Usuario_Mapa() {
		// TODO Auto-generated constructor stub
	}
	
	public long getUsuario_id() {
		return usuario_id;
	}

	public void setUsuario_id(long usuario_id) {
		this.usuario_id = usuario_id;
	}

	public long getMapas_id() {
		return mapas_id;
	}
	
	public void setMapas_id(long mapas_id) {
		this.mapas_id = mapas_id;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (mapas_id ^ (mapas_id >>> 32));
		result = prime * result + (int) (usuario_id ^ (usuario_id >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Usuario_Mapa other = (Usuario_Mapa) obj;
		if (mapas_id != other.mapas_id)
			return false;
		if (usuario_id != other.usuario_id)
			return false;
		return true;
	}
}
Já tentei várias saídas, inclusive deixando as duas colunas com @Id, como uma chave composta... mas até agora não tive sucesso...

Alguém pode ajudar com isso?

[]'s

4 Respostas

L

Ola amigo nao sei se é o q vc precisa mas eu tenho isto no meu mapeamento

package com.NASeguranca.Model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;


@Entity @Table(name="pedidocompraproduto")
public class PedidoCompraProduto {	

	@Embeddable
	public static class Id implements Serializable {
	@Column(name = "codigoPedidoCompra")
	private Long codigoPedidoCompra;
	@Column(name = "codigoProduto")
	private Long codigoProduto;
	public Id() {}
	public Id(Long codigoProduto, Long codigoNumeracaoProduto) {
	this.codigoProduto = codigoProduto;
	this.codigoPedidoCompra = codigoNumeracaoProduto;
	}
	@Override
	public boolean equals(Object o) {
	if (o != null && o instanceof Id) {
	Id that = (Id)o;
	return this.codigoProduto.equals(that.codigoProduto) &&
	this.codigoPedidoCompra.equals(that.codigoPedidoCompra);
	} else {
	return false;
	}
	}
	@Override
	public int hashCode() {
	return codigoProduto.hashCode() + codigoPedidoCompra.hashCode();
	}
	}	
	@EmbeddedId
	private Id id = new Id();	
	
	@ManyToOne
	@JoinColumn(name="codigoPedidoCompra",
	insertable = false,
	updatable = false)
	private PedidoCompra pedidoCompra;	
	
	@ManyToOne
	@JoinColumn(name="codigoProduto",
	insertable = false,
	updatable = false)	
	private Produto  produto;
	
	@Column(name = "valor")
	private Double valor;
	
	@Column(name = "quantidade")
	private int quantidade;
	
	@Column(name = "total")
	private Double total;
	
	
	

}

é um relacionamento onde a tabela de junçao tem a chave de duas outras como vc pode ver acima , sendo que as duas FK forman a Pk desta Entidade, espero que ajude
Abracos

crpablo

Fala ae camarada…

Com esse exemplo que vc postou, agora to conseguindo persistir os dados na tabela com usuarios e mapas repetidos… porém quando dou um findAll() pra pegar todos os dados na tabela e gerar o XML, ele pega os objetos do tipo Usuario_Mapa vazios…

Mas já me deu uma luz… fico te devendo uma gelada… :slight_smile:

crpablo

Falae de novo galerinha...

Com minha classe de relacionamento mapeando as chaves compostas da seguinte forma:
import java.io.Serializable;

import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@SuppressWarnings("serial")
@Entity
public class Usuario_Mapa extends CiaEntity {

	@Embeddable
	public static class Id implements Serializable {

		private long usuario_id;
		private long mapas_id;

		public Id() {

		}

		public Id(long usuario_id, long mapas_id) {

			this.usuario_id = usuario_id;
			this.mapas_id = mapas_id;

		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + (int) (mapas_id ^ (mapas_id >>> 32));
			result = prime * result + (int) (usuario_id ^ (usuario_id >>> 32));
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			final Id other = (Id) obj;
			if (mapas_id != other.mapas_id)
				return false;
			if (usuario_id != other.usuario_id)
				return false;
			return true;
		}
	}
	
	@EmbeddedId
	private Id id = new Id();

	@ManyToOne
	@JoinColumn(name = "usuario_id", insertable = false, updatable = false)
	private Usuario usuarios;

	@ManyToOne
	@JoinColumn(name = "mapas_id", insertable = false, updatable = false)
	private Mapa mapas;

}
Eu consigo persistir os dados na tabela da maneira correta, tipo: Um User com vários mapas e um Map com vários usuários... Porém, quando busco todos os dados na tabela pra gerar meu XML, ele vem da seguinte forma:
<?xml version="1.0" encoding="UTF-8" ?> 
- <java version="1.6.0_03" class="java.beans.XMLDecoder">
- <object class="java.util.ArrayList">
- <void method="add">
  <object class="Usuario_Mapa" /> 
  </void>
- <void method="add">
  <object class="Usuario_Mapa" /> 
  </void>
  </object>
  </java>
Ou seja, os dados contidos nas tabelas não são serializados. Com minhas class da seguinte forma:
import javax.persistence.Entity;
import javax.persistence.Id;

@SuppressWarnings("serial")
@Entity
public class Usuario_Mapa extends CiaEntity {

	 @Id
	 private long usuario_id, mapas_id;
	
	 public Usuario_Mapa() {
		 // TODO Auto-generated constructor stub
	 }
	
	 public long getUsuario_id() {
		 return usuario_id;
	 }
	
	 public void setUsuario_id(long usuario_id) {
	 this.usuario_id = usuario_id;
	 }
	
	 public long getMapas_id() {
		 return mapas_id;
	 }
	
	 public void setMapas_id(long mapas_id) {
		 this.mapas_id = mapas_id;
	 }
	
	 @Override
	 public int hashCode() {
		 final int prime = 31;
		 int result = 1;
		 result = prime * result + (int) (mapas_id ^ (mapas_id >>> 32));
		 result = prime * result + (int) (usuario_id ^ (usuario_id >>> 32));
		 return result;
	 }
	
	 @Override
	 public boolean equals(Object obj) {
		 if (this == obj)
			 return true;
		 if (obj == null)
			 return false;
		 if (getClass() != obj.getClass())
			 return false;
		 final Usuario_Mapa other = (Usuario_Mapa) obj;
		 if (mapas_id != other.mapas_id)
			 return false;
		 if (usuario_id != other.usuario_id)
			 return false;
		 return true;
	 }
}
Eu não consigo persistir tabelas iguais para usuários diferentes, mas o XML é gerado da maneira correta, como vcs podem ver abaixo:
<?xml version="1.0" encoding="UTF-8" ?> 
- <java version="1.6.0_03" class="java.beans.XMLDecoder">
- <object class="java.util.ArrayList">
- <void method="add">
- <object class="Usuario_Mapa">
- <void property="mapas_id">
  <long>1</long> 
  </void>
- <void property="usuario_id">
  <long>1</long> 
  </void>
  </object>
  </void>
- <void method="add">
- <object id="Usuario_Mapa0" class="Usuario_Mapa">
- <void property="mapas_id">
  <long>2</long> 
  </void>
- <void property="usuario_id">
  <long>2</long> 
  </void>
  </object>
  </void>
  </object>
  </java>

A minha necessidade seria a união desses dois, lógico que descartando os dados em branco no xml gerado pela primeira class e a não permissão de persistir chaves duplicadas da segunda class...

Alguém tem alguma idéia?

Abraço

crpablo

Ainda não encontrei um resolução pre esse problema…

Alguém ae pode ajudar?

[]'s

Criado 21 de fevereiro de 2008
Ultima resposta 25 de fev. de 2008
Respostas 4
Participantes 2