Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Dúvida com comportamento padrão do JPA

No sistema que estou desenvolvendo tenho a necessidade de salvar um artigo, e nesse artigo devo salvar também o autor e o usuário que realizou a última edição neste arquivo(tanto para auditoria futura quanto para algumas lógicas que dependem do nível do usuário logado).

Para tal tarefa eu pego sempre o usuário que está na sessão e seto como autor, caso seja uma inclusão ou usuarioUltimaAlteracao caso seja uma alteração. Para tanto tenho um relacionamento de Artigo para Usuario

@Entity
public class Artigo{
@ManyToOne
@JoinColumn(name="usuario_criacao)
private Usuario autor;
}

no momento de salvar

public  void salvarArtigo(Artigo artigo){
artigo.autoria(usuarioQueVemDaSessao);
//....outros procedimentos
}

Tudo isso funciona, mas devido a um comportamento específico do jpa, notei um comportamento indesejado. Toda vez que carrego um artigo, por padrão como o JPA considera os relacionamentos ManyToOne como EAGER, ele vai fazer o select do autor, e do usuário da ultima alteração. O problema não é o select em si, mas sim que esse select traz as senhas do usuário junto. para contornar isso só escrevendo queries planejadas, mas todo o sistema gira em torno dos Artigos, teria que modificar praticamente todas as minhas queries, oque daria muito trabalho. Existe alguma estratégia para contornar esse problema?

6 respostas

Olá Ricardo,

Acredito que basta você declarar a relação com o usuário como Lazy, conforme o exemplo abaixo:

@Entity
public class Artigo{
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="usuario_criacao)
private Usuario autor;
}

infelizmente isso não funciona, pelo menos não na implementação do hibernate, ele ignora esse lazy em relacionamentos OneToOne e ManyToOne

Dennis, acredito que eu possa ter me enganado, oque eu tenho certeza que o Hibernate ignora é quando declaramos Lazy em uma propriedades simples, por exemplo:

public class Usuario {
@Basic(fetch = FetchType.LAZY)
private String senha;
}

oque seria o ideal, pois mesmo que o lazy funcione no manyToOne, vou ter que carregar o usuário de qualquer forma, pois preciso de algumas informações do usuário na tela, então eu iria cair no mesmo problema

Olá Ricardo,

Acredito que realmente funciona, o que voce poderia fazer, seria deixar como Lazy e nos casos que voce precisar obter a informacao do usuário voce poderia obter efetuando apenas um getAutor() enquanto o Objeto ainda está em estado managed ou entao fazer uma query com fetch join deixando explicito que voce quer carregar os dados do usuário.

A ideia é deixar como o default o comportamento que voce mais utiliza e nas excecoes voce faz de forma diferenciada.

Dennis, esse cara aqui escreveu um artigo que talvez explane melhor o problema, o problema não é quanto a carregar os dados do usuário, mas sim deixar disponível dados sensíveis como a senha(mesmo que criptografada),

https://blog.goyello.com/2012/01/10/not-store-user-credentials-database/

solução!

Agora entendi bem qual é o problema, achei bastante interessante o artigo, acredito que a melhor solução seria mesmo salvar os dados de credenciais em outra tabela.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software