Tenho um modelo semelhante ao código abaixo (uma corrente de objetos com relacionamentos um-pra-um compartilhando a chave primária):
@Entity
class C {
@Id
private long id;
@OneToOne(fetch=FetchType.EAGER)
@PrimaryKeyJoinColumn
private B b;
//...
}
@Entity
class B {
@Id
private long id;
@OneToOne(fetch=FetchType.EAGER)
@PrimaryKeyJoinColumn
private A a;
//...
}
@Entity
class A {
@Id
private long id;
//...
}
Gostaria de uma forma otimizada de buscar um id “X” em A, retornando:
um objeto do tipo C (contendo b e a), caso exista C, B e A tal que X = c.id = b.id = a.id
um objeto do tipo B (contendo a), caso só exista B e A tal que X = b.id = a.id (não existe c.id = X)
um objeto do tipo A, caso só exista A tal que X = a.id (não existe b.id = c.id = X)
Teria como eu fazer essa consulta em uma única instrução HQL, ou só mesmo fazendo 1 consulta para cada caso? Não me importo de fazer várias consultas, contanto que eu saiba que não existe uma forma otimizada de se fazer isso…
Pelo que entendi, as chaves sempre vão ser unicas, portanto A.id = B.id = C.id, correto?
Vc pode criar os mapeamentos e chaves unicas inversas e fazer a consulta a partir de A…
Não me lembro direito agora, mas existe uma opção de mapeamento inverso no Hibernate… com isso vc tem a chave espelhada tanto na entidade que doa a chave quanto na entidade que recebe a chave…
Se vc mapear assim, vc consegue fazer:
[quote=lmprates]Provavelmente utilizando algumas subquery’s e retornando um map você consiga fazer tudo em uma só.
Só por curiosidade, qual é a aplicação destas query’s, algum projeto ou universidade ?
[]'s[/quote]
É para um projeto “grandinho”. É uma aplicação integrada, com vários módulos. Vou tentar explicar ± o problema:
Temos pessoas físicas, pessoas jurídicas, fornecedores, contadores, instituições e um tanto de outros papéis que são “pessoas”.
A classe Pessoa é como se fosse a classe “A” lá de cima. Imagine a classe “B” como a classe Funcionario, e a classe “C” como a classe Professor.
Digamos que o usuário quer cadastrar um professor chamado João. Ele deseja entrar no formulário de cadastro de professores, digitar o CPF de João e o sistema deverá automaticamente trazer para formulário os campos correspondentes a Professor (prof + func + pessoa), caso o professor João já esteja cadastrado no banco. Se não existir “cpf joão professor”, mas existir “cpf joão funcionário”, trazer os dados de João Funcionário (func + pessoa). Se não existir João funcionário, mas existir João Pessoa, trazer João Pessoa. Se não existir, não trazer nada e o usuário vai ter q digitar todos os dados do professor João que ele está cadastrando.
Suponha que a classe Fornecedor está no mesmo nível da classe Funcionário (ou B) (ou seja, ela possui uma referência um-pra-um p/ classe Pessoa). Depois de um tempo, João passou a ser, além de professor, um fornecedor. O usuário deseja entrar no cadastro de fornecedores, digitar o CPF de joão e o sistema deverá trazer os campos de Pessoa (já que os campos de funcionários/professor não se aplicam aqui).
Aqui no trab nós não conseguimos usar herança para resolver esse problema. Tivemos que criar uma “herança falsa”, usando composição mesmo. Um dos problemas que tivemos ao tentar usar herança estão em outro post meu: http://www.guj.com.br/posts/list/102533.java
A princípio vou fazer uma consulta de cada vez, pq o importante agora é deixar funcionando. Depois vou pesquisar sobre a sua idéia de map e subquery’s!
Pela explicação que eu dei acima, veja que não é aceitável, neste caso, usar relacionamento bi-direcional (não podemos deixar que a classe Pessoa tenha uma referência para todas as outras classes que fazem referência a ela (Pessoa)), então essa solução não se aplica…