GORM Herança: como reaproveitar o registro da super classe?
02/06/2010 00:00
0
Pessoal, antes de começar gostaria de dizer que tenho gostado muito do Grails.
Estamos conseguindo criar com muita facilidade uma aplicação que se feita em Java exigiria muito mais trabalho.

Pois é, facilidades a parte, vamos ao problema:

É o seguinte:
em uma herança, não consigo reaproveitar em uma subclasse o registro da SUPER CLASSE salvo por outra subclasse.

Possuo uma classe Pessoa da qual herdam várias outras, tais como Analista e Diretor.
Acontece que a mesma Pessoa é Analista e Diretor.

Quando salvo um Analista não consigo usar os mesmos dados dele para salvar um Diretor de forma que fique claro que são a mesma Pessoa.

Caso não queiram ler todo o post, penso que podem ir direto ao tópico "Simulando o problema:"

Explicando o problema:

Na aplicação que estamos desenvolvendo um existem alguns conceitos que não possuem um CPF. É o caso do Projetista, que no nosso caso não possui CPF. Além do Projetista existem outros casos de pessoas sem CPF ou qualquer código único.
Um Analista é uma Pessoa e um Diretor também.

Estou usando a estratégia uma tabela para cada classe de domínio, para separar melhor os conceitos (tablePerHierarchy false).

Quando uma Pessoa possui um código identificador (no caso do CPF para o Diretor) este código é usado para ser o seu id.
Quando a Pessoa não possui um código identificador eu uso uma classe geradora de código e gero um id com 15 dígitos, que não pode ser confundido com o CPF ou com o CNPJ (existe também o conceito de Empresa, que possui CNPJ, mas que é irrelevante para o problema que preciso resolver).

Vejam a seguir o código a CLASSE Pessoa:
import utils.GeradorDeCodigo;

class Pessoa {
public final static String TIPO_PESSOA_FISICA = "PF";
public final static String TIPO_PESSOA_JURIDICA = "PJ";

BigInteger codigoIdentificador;
String nome;
String nacionalidade="Brasileira";
String telefone;
String email;
String tipo = TIPO_PESSOA_FISICA;

static transients=['codigoIdentificador'];
static mapping = {
tablePerHierarchy false
table 'pf_pessoa'
sort 'nome'
version true
id generator:'assigned', column:'pes_id'
nome column:'pes_nome'
nacionalidade column:'pes_nacionalidade'
telefone column:'pes_telefone'
email column:'pes_email'
tipo column:'pes_tipo'
}

/* EVENTOS */
transient beforeInsert = {
if ((this.codigoIdentificador) && (this.codigoIdentificador > 0)) {
this.id = this.codigoIdentificador;
} else {
this.id = GeradorDeCodigo.gerarProximo(Pessoa.class.getName());
}
}
}


Agora, vejam o código da CLASSE Analista:
class Analista extends Pessoa {
String situacao;
String cpf;

void setCpf(String value) {
// seta o Código Identificador do conceito de Pessoa
this.codigoIdentificador = new BigInteger(value);
}

static mapping = {
table 'pf_analista'
version true
id column: 'ana_id'
situacao column:'ana_situacao'
cpf column:'ana_cpf'
}

static constraints = {
situacao(maxSize: 1, inList:["A", "I"])
cpf(size: 0..11, blank:true, nullable:true)
}
}


Por fim, vejam o código da CLASSE Diretor:
class Diretor extends Pessoa {
String cpf;

void setCpf(String value) {
// seta o Código Identificador do conceito de Pessoa
this.codigoIdentificador = new BigInteger(value);
}

static mapping = {
tablePerHierarchy false
table 'pf_diretor'
sort 'nome'
version true
id column: 'dr_id'
cpf column:'dr_cpf'
}

static constraints = {
cpf(size: 0..11, blank:true, nullable:true)
}
}


Com as classes acima, possuo no banco de dados as seguintes tabelas: pf_pessoa, pf_analista e pf_diretor;

Simulando o problema:
Acontece que a mesma Pessoa é Analista e Diretor.

Quando salvo um Analista não consigo usar os mesmos dados dele para salvar um Diretor de forma que fique claro que são a mesma Pessoa.

Para simular o problema criei um código que faz o seguinte:
1 - Cria e salva um Analista. Indiquei de propósito um CPF para ele.
2 - Cria um Diretor e tenta salvar com o mesmo CPF do Analista. Estou querendo indicar que esta Pessoa é aquela mesma Pessoa que é Analista.

Vejam o código:
class testeHerancaController {

def testar = {
Acionista oAcionista = new Acionista();
oAcionista.nome = "weber3";
oAcionista.email = "webermiranda3@sic.goias.gov.br";
oAcionista.telefone = "6232015536";
oAcionista.cpf = "12345678901";
oAcionista.save(flush:true);

Diretor oDiretor = new Diretor();
oDiretor.nome = "weber3";
oDiretor.email = "webermiranda3@sic.goias.gov.br";
oDiretor.telefone = "6232015536";
oDiretor.cpf = "12345678901";
oDiretor.save(flush:true); // ERRO AQUI

}
}


Quando eu mando salvar o Diretor (oDiretor.save) recebo um erro de chave duplicada no bacno de dados.

Neste exemplo eu simplifiquei a situação para facilitar o entendimento, mas os conceitos que herdam de Pessoa possuem vários atributos que diferenciam de um conceito para outro.

A pergunta é:
Como vou fazer para conseguir dizer que um Diretor é uma Pessoa que já existe em minha base de dados?

Valeu pela atenção e espero que possam me ajudar.
Tags: Tópicos avançados


0
webermiranda,

Acredito que o seu problema seja conceitual e não do framework hibernate ou grails.

O que você ta querendo fazer é algo que java não aceita, Herança multipla. Eu digo isso pq para o hibernate, nessa situacao quando voce tiver um analista ou diretor, o hibernate passa a encarar essa instacia apenas como a sub classe e nao mais como apenas pessoa.

Se você mudar a relacao entre pessoa e analista e diretor, deixando de ser uma herança para ser um relacionamento muitos pra um, você conseguirá resolver seu problema.


Espero ter ajudado.
04/06/2010 00:00


0
igorhara tem razão, mesmo que Analista e Diretor sejam do tipo Pessoa o que você está persistindo no banco de dados é são as entidades Analista e Diretor e não pessoa. Acho que a solução que o igorhara citou é também é a melhor para resolver este teu problema!
04/06/2010 00:00



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto