Pessoal, estou ha um tempo batendo cabeca aqui e depois de vasculhar muita coisa nao consegui achar uma saida.
Basicamente é a ideia que criar tipos de dados mais complexos para os usuarios do sistema relacionarem como eles quiserem.
Tenho o seguinte cenário:
@Entity
@SequenceGenerator(name = "SEQ_TIPO_DADOS_PESSOA", sequenceName = "SEQ_TIPO_DADOS_PESSOA", allocationSize = 1)
public class TipoDadosPessoa implements Serializable {
private static final long serialVersionUID = 930238550723053990L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "SEQ_TIPO_DADOS_PESSOA")
private int cdTipoDadosPessoa;
private String nmTipoDadosPessoa;
private String tpDados;
// get's e set's
}
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@SequenceGenerator(name = "SEQ_PESSOA", sequenceName = "SEQ_PESSOA", allocationSize = 1)
public class Pessoa implements Serializable {
private static final long serialVersionUID = -43591332807421018L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "SEQ_PESSOA")
private int cdPessoa;
private String tpPessoa; // Fisica - Juridica
private String nmPessoa;
private String nrCpfCnpj;
// get's e set's
}
@Entity
@SequenceGenerator(name = "SEQ_DADOS_PESSOA", sequenceName = "SEQ_DADOS_PESSOA", allocationSize = 1)
public class DadosPessoa implements Serializable {
private static final long serialVersionUID = 3644031969004966534L;
private String dsDescricao;
@EmbeddedId
private DadosPessoaPK chaveComposta;
// get's e set's
}
@Embeddable
public class DadosPessoaPK implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="cdTipoDadosPessoa")
private TipoDadosPessoa cdTipoDadosPessoa;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "cdPessoa")
private Pessoa cdPessoa;
// get's e set's
}
A base de dados:
Pessoa
cdPessoa = 1 , nmPessoa = arthur , tpPessoa = F , cpfCnpj = 1234
TipoDadosPessoa
cdTipoDadosPessoa = 1, nmTipoDadosPessoa = CNH , tpDados = Integer
cdTipoDadosPessoa = 2, nmTipoDadosPessoa = Numero de Sobrinhos , tpDados = Integer
cdTipoDadosPessoa = 3, nmTipoDadosPessoa = Numero de Automoveis , tpDados = Integer
cdTipoDadosPessoa = 4, nmTipoDadosPessoa = Aniversario do Avo , tpDados = Date
DadosPessoa
cdPessoa = 1 , cdTipoDadosPessoa = 1 , dsDescricao = 000111222
Preciso trazer todos os TipoDadosPessoa mesmo que nao haja um relacionamento com pessoa.
No mundo relacional seria relativamente simples:
select dp.cdPessoa,tdp.cdTipoDadosPessoa, dp.dsdescricao from dadospessoa dp
left join pessoa p on p.cdPessoa = dp.cdPessoa
right join tipodadospessoa tdp on tdp.cdTipoDadosPessoa = dp.cdTipoDadosPessoa
where dp.cdPessoa = 1 or dp.cdPessoa is null
O resultado do SQL seria:
DadosPessoa
cdPessoa = 1 , cdTipoDadosPessoa = 1 , dsDescricao = 000111222
cdPessoa = null , cdTipoDadosPessoa = 2 , dsDescricao = null
cdPessoa = null , cdTipoDadosPessoa = 3 , dsDescricao = null
cdPessoa = null , cdTipoDadosPessoa = 4 , dsDescricao = null
Porem, ao montar o hql nao estou sabendo manipular a chave composta embarcada, usando o hibernate tools eu consigo notar alguns comportamentos que me chamam a atencao
O HQL:
select dp from DadosPessoa dp
right join dp.chaveComposta.cdTipoDadosPessoa t
left join dp.chaveComposta.cdPessoa p
where p.cdPessoa = 1 or p is null
Desta forma ele me traz 3 objetos, sendo 3 deles null ( provavelmente pelo produto cartesiano que deu ) e um certinho ( unico relacionado )
Na minha cabeca, a forma que eu estava pensando o hibernate montaria “metade” do objeto pra mim, traria 4 objetos DadosPessoa, porem 3 deles sem o relacionamento de pessoa. nao sei se fui claro.
Vamos a um exemplo de como eu imaginava ( e gostaria que voltasse assim )
DadosPessoa
chaveComposta.cdPessoa.cdPessoa = 1 , chaveComposta.cdTipoDadosPessoa.cdTipoDadosPessoa = 1 , dsDescricao = 000111222
chaveComposta.cdPessoa = null , chaveComposta.cdTipoDadosPessoa.cdTipoDadosPessoa = 2
chaveComposta.cdPessoa = null , chaveComposta.cdTipoDadosPessoa.cdTipoDadosPessoa = 3
chaveComposta.cdPessoa = null , chaveComposta.cdTipoDadosPessoa.cdTipoDadosPessoa = 4
O HQL executa, porem quando vou varrer a lista de retorno, ele da uma excessao de nullpointer obviamente por acessar metodos de um objeto nulo.
Como o desespero eh grande, a velha tatica de brutal force entrou em acao.
como por exemplo
select new DadosPessoa( new DadosPessoaPK( p , tp ) ) from DadosPessoa dp
right join dp.chaveComposta.cdTipoDadosPessoa tp
left join dp.chaveComposta.cdPessoa p
where p.cdPessoa = 1
Mas esse ae nem compila…
Uma outra tentativa, porem esta gera uns joins muito doidos com entidades que eu nao explicitei no hql, por exemplo
select p , tp from DadosPessoa dp
right join dp.chaveComposta.cdTipoDadosPessoa tp
left join dp.chaveComposta.cdPessoa p
Nao sei se fui claro… mas realmente nao faco a minima ideia de como resolver isso… alguem se habilita??
Grato desde já!