Onetoone no hibernate usando colunas diferentes na relação

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]

e como esta o relacionamento na classe Pessoa??

posta o relacionamento inverso porfavor…

[quote=darklordkamui]e como esta o relacionamento na classe Pessoa??

posta o relacionamento inverso porfavor…[/quote]

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;  

o que seria esse dadospessoas?

e o atributo cpf esta aonde?

[quote=darklordkamui]o que seria esse dadospessoas?

e o atributo cpf esta aonde?[/quote]

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

[quote=renatomattos2912][quote=darklordkamui]o que seria esse dadospessoas?

e o atributo cpf esta aonde?[/quote]

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

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…

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.

se voce fizer isso…

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

funciona?

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%

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

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();
}

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.

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

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

Aqui mostra como fazer JOINS: JPA Consultas e Dicas

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.

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

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?