Mapeamento Hibernate Annotation com Id sendo um objeto

11 respostas
alessandro.fawkes

[color=red]TÓPICO ENCERADO[/color]

Olá galera, estou fazendo um mapeamento com hibernate annotations usando o id não como sendo um tipo primitivo, mas sim uma classe:

//=============

//classe mapeada

[color=blue]@Entity

public class Carro implements Serializable {

@Id

PKLong pk = new PKLong();

private String marca;[/color]

//-----------------------

//classe que armazena o pk

[color=blue]public class PKLong implements Serializable {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

private long codigo;[/color]

//=============

no banco, quando eu faço a persistência de um Carro o campo id da tabela é uma string enorme, acredito que seja a clase PKLong serializada:

[color=blue]ac  ed  00  05  73  72  00  0f  62  65  61  6e  73  2e  70  6b  2e  50  4b  4c  6f  6e  67  7b  6f  f1  19  58  39  22  86  02  00  01  4a  00  06  63  6f  64  69  67  6f  78  70  00  00  00  00  00  00  00  00[/color]

a minha pergunta é a seguinte:
como o hibernate lida internamente com uma id que é um objeto?
Como eu posso estar recuperando essa classe? antes eu fazia isso por um número (1, 2, 3, …), mas e agora?

11 Respostas

guilherme.chapiewski

A primeira coisa que você tem que fazer é descobrir/decidir o que diabos é esse seu campo ID :slight_smile:

Você está falando que é uma String enorme, certo? E tá com cara mesmo de ser algum tipo de GUID.

Se for isso, porque você ao invés de tratá-lo como um objeto simplesmente não o trata como uma String?

alessandro.fawkes

Para o usuário buscar por um id numérico correspondente ao Carro que ele quer buscar é fácil? Mas como eu vou pedir a ele toda essa string?

guilherme.chapiewski

Pergunta: porque diabos um usuário iria querer buscar por um ID de carro (ainda mais um ID desses)?

Para mim parece mais razoável que ele busque pelo nome, modelo, cor, ou qualquer outro tipo de coisa mas não o ID. Idealmente isso nem deveria aparecer para o usuário.

E finalizando, usar um ID desse tipo para uma tabela de “carros” me parece totalmente inadequado.

jonatascp

Alessandro,

Só acho necessário o uso de um objeto representando uma chave primária, quando se refere a uma chave composta, até porque o id do carro será 'codigo' que é um tipo primitivo, mais você deve ter seus motivos de querer utilizar essa classe que representa o id de carro, acho que a solução é a mesma de chave composta.
  1. A classe Carro não é obrigada a implementar Serializable, só a classe PKLong;

  2. Isso aqui: “PKLong pk = new PKLong()” tá estranho, vamos colocar “private PKLong pk”;

  3. Substituir o annotation @Id por @EmbeddedId, na declaração do atributo pk na classe carro, indicando assim que a chave estará na classe PKLong;

  4. Adicionar o annotation @Embeddable, na classe PKLong, indicando assim que a classe PKLong representará uma chave;

  5. Retirar o annotation @Id do atributo código na classe PKLongn, pois isso está sendo feito no item 4;

    Satisfazendo as observações descritas acima, o código ficaria assim:
    

//-----------------------
//classe mapeada
[color=blue]@Entity
public class Carro {

@EmbeddedId
private PKLong pk;
private String marca;[/color]

//classe que armazena o pk
[color=blue]@Embeddable
public class PKLong implements Serializable {

@GeneratedValue(strategy=GenerationType.IDENTITY)
private long codigo;[/color]

//-----------------------

Espero que funcione, mais acho que você deve analisar bem se é realmente necessário o uso de uma classe, para representar um único atributo primitivo.
alessandro.fawkes

Obrigado, vou testar e ver se isso funciona.

O que eu quero com isso é o seguinte:

Hoje eu estou usando o banco de dados Derby, futuramente (depois que o programa for instalado) irei usar mySql, sei que ambos aceitam a estratégia IDENTITY como generator de primaryKey, porém se algum dia um banco não suportar eu terei que dar manutenção em todos os meus pojo/bean? Por esse motivo eu estou querendo tirar essa anotação para uma única classe, mas como fazer isso com anotações?

Já procurei na documentação do hibernate e não encontrei nada.

a alternativa acima foi uma das soluções que encontrei, mas estou com problemas. alguém conheçe outra.

quanto ao recuperar por id, recupero por ele por que é assim que o hibernate.session busca um registro no banco:

[color=blue]import org.hibernate.Session;



public Carro recuperar(Long id) {

return (Carro) this.session.load(this.persistenceClass, id);

}

[/color]

obrigado pelas idéias propostas até agora, até hoje a noite eu divulgo o resultado do código do jonatascp

J2Alex

Basta você criar uma superclasse com o seu Id anotado e usar a anotação @MappedSuperclass nessa classe.

alessandro.fawkes

mas com essa anotação eu poderei ter mapeamento na superclasse e também na subclasse? pois minha intenção é colocar somente a anotação do id nessa superclasse.

J2Alex

Você pode fazer isso:

@MappedSuperclass
public abstract class Carro {

    @Id
    private Long id;

    ...

}

@Entity
public class Fusca extends Carro {

    // Demais campos específicos da classe

}
alessandro.fawkes

J2Alex, nesse caso as duas classes devem implementar seralizable e estarem mapeadas, estou certo?
vou testar hj a noite e posto o resultado.

obrigado

alessandro.fawkes

Blz, deu certo, muito obrigado J2Alex.

Se eu tiver mais de uma classe extendendo de PKLong, no banco, vai ter um generator pra cada classe ou vai ser um só para todas as classes?

bom, deixa eu testar, já pedi demais nesse post.

posto o resultado a seguir.

alessandro.fawkes

Uhuuu, para cada classe um generator.

Muito obrigado,
[color=red]
TÓPICO ENCERADO[/color]

Criado 12 de setembro de 2007
Ultima resposta 13 de set. de 2007
Respostas 11
Participantes 4