Onetoone no hibernate usando colunas diferentes na relação

17 respostas
R

Bom dia,

Estou com um problema para fazer um onetoone no hibernate, tenho duas tabelas que se relacionam por colunas que não são chaves primarias, ae eu uso a anotação @joincolumn pra informar qual coluna eu quero q seja utilizada na relação, porem isso funciona só para uma das entitys, a outra continua usando o id, por exemplo, tenho duas tabelas “pessoa” e “dadosPessoa” e cada tabela dessa tem 4 campos (Pessoa: id, nome, idade, cpf) (dadosPessoa: id, rg, cpf, descricao), o q eu quero fazer é q ao invés das tabelas se ralcionarem pelos ids, quero q elas se ralacionem pelo cpf, o maximo q consegui fazer foi relacionar id de uma com cpf da outra, mas nunca o cpf das duas, segue abaixo o codigo:

Pessoa:

@OneToOne(fetch = FetchType.LAZY, optional=true)
@JoinColumn(name="cpf")
private Pessoa pessoa;

dadosPessoa:

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "pessoa")
private DadosPessoa dadosPessoa;

sql gerado:

select
	this_.id as id0_1_,
	this_.nome as nome0_1_,
	this_.idade as idade0_1_,
	this_.cpf as cpf0_1_,
	b1_.id as id1_0_,
	b1_.rg as rg1_0_,
	b1_.cpf as cpf1_0_,
	b1_.descricao as descicao1_0_ 
from
	pessoa this_ 
inner join
	dadosPessoa b1_ 
	on this_.id=b1_.cpf

Aqui segue o sql da forma q eu quero que ele fique e nao estou conseguindo (em negrito):

select
	this_.id as id0_1_,
	this_.nome as nome0_1_,
	this_.idade as idade0_1_,
	this_.cpf as cpf0_1_,
	b1_.id as id1_0_,
	b1_.rg as rg1_0_,
	b1_.cpf as cpf1_0_,
	b1_.descricao as descicao1_0_ 
from
	pessoa this_ 
inner join
	dadosPessoa b1_ 
	[b]on this_.cpf=b1_.cpf[/b]

17 Respostas

D

e como esta o relacionamento na classe Pessoa??

posta o relacionamento inverso porfavor…

R

darklordkamui:
e como esta o relacionamento na classe Pessoa??

posta o relacionamento inverso porfavor…

ja postei os dois acima, segue abaixo novamente:

Pessoa:

@OneToOne(fetch = FetchType.LAZY, optional=true)  
@JoinColumn(name="cpf")  
private Pessoa pessoa;

dadosPessoa:

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "pessoa")  
private DadosPessoa dadosPessoa;
D

o que seria esse dadospessoas?

e o atributo cpf esta aonde?

R

darklordkamui:
o que seria esse dadospessoas?

e o atributo cpf esta aonde?

tenho duas tabelas “pessoa” e “dadosPessoa” e cada tabela dessa tem 4 campos (Pessoa: id, nome, idade, cpf) (dadosPessoa: id, rg, cpf, descricao)

D

renatomattos2912:
darklordkamui:
o que seria esse dadospessoas?

e o atributo cpf esta aonde?

tenho duas tabelas “pessoa” e “dadosPessoa” e cada tabela dessa tem 4 campos (Pessoa: id, nome, idade, cpf) (dadosPessoa: id, rg, cpf, descricao)

então o cpf em dados pessoa é chave unica certo? sendo que nao havera outro objeto de dados pessoa com o mesmo cpf…

se for esse o caso, vc nao precisa ligar direto ao cpf… vc pode ligar ao id do dadosPessoa… mas ai voce pode modificar para Eager já que é um relacionamento OneToOne…

R

então, o cpf é unico pra cada pessoa, nao ira se repetir, mas ele nao é chave primaria em nenhuma das tabelas, o q quero é relacionar as tabelas pelo cpf mas o hibernate esta fazendo a relação pelos ids das tabelas, só q os ids das tableas não são relacionaveis, ou seja, o id 1 de uma tabela não indica a mesma pessoa do id 1 da outra tabela, mas o cpf sim.

D

se voce fizer isso…

@OneToOne(fetch = FetchType.LAZY, optional=true) @JoinColumn(name="dadosPessoa_cpf") private Pessoa pessoa;

funciona?

R

acontece isso:

inner join
dadosEscola b1_ 
on this_.id=b1_.cpf

isso resolve 50%, repare ali onde esta this_.id, isso representa a Escola, eu precisaria q isso virasse this_.cpf, o exemplo q vc me passou fez o b1_.id virar b1_.cpf, por isso resolveu 50%

H

Você não poderia transformar cpf em id não?

R

na verdade não pq as tabelas ja estao prontas e populadas, não posso mudar muita coisa nelas, vou tentar explicar meu problema de forma mais facil, o que acontece é que eu poderia usar o metodo createSQLQUery do hibernate e escrever normalmente esse relacionamento utilizando o cpf, só q com isso eu nao consigo guardar os dados em uma entity e no meu front eu nao conseguiria exibir os dados usando esta forma “pessoa.nome, pessoa.cpf…” o maximo q eu consigo fazer trazendo os dados por query nativa é guarda-los em um list e no front exibir desta forma “pessoa[0], pessoa[1]…” e isso vai deixar meu front muito dificil de dar manutenção pq é bem mais facil saber o q é pessoa.nome do q pessoa[0], e caso eu mude a query a ordem da list tmb mudaria e eu teria q rever todos os dados do front caso eu use do jeito pessoa[0], por isso eu resolvi usar criteria para trazer os dados, porem o criteria so funciona se eu reacionar as duas entitys no one to one, ae com isso surgiu este problema q estou tentando solucionar aqui com vcs.

o codigo do criteria:

public Pessoa carrega(Long cpf) {
	return (Pessoa) session.createCriteria(Pessoa.class)
			.createAlias("dadosPessoa", "b")
			.uniqueResult();
}
H

Até onde sei, só se faz o join “automático” por ids. Você poderia carregar sempre o objeto por consulta. Deixe todo mundo lazy e aí você dispara uma JPQL carregando o objeto pelo cpf.

D

concordo com voce, ele tinha que transformar o cpf pelo menos em chave composta… ou em id mesmo…

R

Voce poderia me dar um exemplo disso que me indicou, pois nao faço ideia de como fazer isso q vc disse.

H

Aqui mostra como fazer JOINS: JPA Consultas e Dicas

R

fiz uma alteração na entity baseado no q vcs falaram e resolveu, nao sei se isso ira gerar algum problema futuro mas acredito q nao, eu alterei o id da tabela para o cpf, acredito q isso tenha alterado apenas na entity e nao vai causar problemas no banco, pois é apenas uma tabela de consulta entao, aparentemente deu certo.

D

acredito que não… más se por ventura acontecer você vai adptando, não existe um codigo imune a mudanças então não se preoculpe com os problemas, deixe que os problemas venha a você =D

R

puts surgiu um problema estranho, na tela onde eu mostro a pagina da pessoa acontece apenas um select, porem na tela de resultado de busca onde aparecem varias pessoas, alem de executar o select para tarzer as pessoas, ele tmb executa o select de relacionamento do one to one para cada pessoa q veio do resultado do select anterior, ou seja, ele ta fazendo muitas consultas desnecessárias, o estranho é q eu nem chamo essas consultas, acredito q elas sejam feitas por causa do one to one mesmo, sera q tem como barrar isso? executar o relacionamento apenas quando eu precisar? e nao toda vez q eu consultar a entity pessoa?

Criado 28 de janeiro de 2013
Ultima resposta 28 de jan. de 2013
Respostas 17
Participantes 3