Hibernate - Dúvidas: @Formula e carregar uma entidade parcialmente

Boa tarde galera, ainda tenho algumas dúvidas em relação ao Hibernate em questão de performance, então gostaria de saber se existe melhores práticas.

Primeiramente eu gostaria de saber se ao buscar um dado no banco, eu consiga trazer somente os dados que eu preciso para a entidade que estou buscando, tipo HQL (SELECT pessoa.id FROM pessoa WHERE id=:parametro)… Eu gostaria receber de ele como um objeto PESSOA só que somente com o id preenchido (somente exemplo).

Outra dúvida, é que eu possuo uma @Formula pra saber a quantidade do relacionamento:

@Formula("(SELECT COUNT(endpro.endpro_id) FROM endereco e LEFT JOIN endereco_produto endpro ON e.end_id = endpro.end_id WHERE e.end_id = end_id)") private Integer countEnderecoProduto;
O problema é que qualquer coisa que eu faço com essa entidade que possui essa formula, a formula é executada sempre. Se for possível fazer o que eu perguntei primeiro, já vai resolver. Se não eu precisaria de alguma boa prática de executar isso somente quando eu preciso.

Obrigado pela atenção!
Abraço a todos.

Bom, para o primeiro caso “Popular apenas alguns campos de um objeto” existe uma maneira que é informada na documentação do Hibernate, vc basicamente precisa de um construtor setando o campo que vc quer na sua classe e na query vc chama esse construtor com um new no select, exemplo:

Classe (Model)

public class Teste{
    @Id
    private Integer id;
    private String nome;

    //Construtor vazio
    public Teste(){};

    //Construtor com o id
    public Teste(Integer id){
        this.id = id;
        }

    getters e setters...
    }

Select populando apenas o id do model Teste

(Teste) session.createQuery("select new Teste(t.id) from Teste t where t = :teste").setParameter("teste",new Teste(1)).uniqueResult();

Já no seu segundo caso vc pode adicionar uma anotação de carregamento Lazy nesse campo para ele carregar só quando vc resgatar o campo com getter:

@Formula("(SELECT COUNT(endpro.endpro_id) FROM endereco e LEFT JOIN endereco_produto endpro ON e.end_id = endpro.end_id WHERE e.end_id = end_id)")  
@Basic(fetch=FetchType.LAZY) //Adiciona essa linha
private Long countEnderecoProduto;

Obs*: Esse tipo de questão está mais apropriada para o GUJ Respostas!

[quote=Mickdark]Bom, para o primeiro caso “Popular apenas alguns campos de um objeto” existe uma maneira que é informada na documentação do Hibernate, vc basicamente precisa de um construtor setando o campo que vc quer na sua classe e na query vc chama esse construtor com um new no select, exemplo:

Classe (Model)

public class Teste{
    @Id
    private Integer id;
    private String nome;

    //Construtor vazio
    public Teste(){};

    //Construtor com o id
    public Teste(Integer id){
        this.id = id;
        }

    getters e setters...
    }

Select populando apenas o id do model Teste

(Teste) session.createQuery("select new Teste(t.id) from Teste t where t = :teste").setParameter("teste",new Teste(1)).uniqueResult();

Já no seu segundo caso vc pode adicionar uma anotação de carregamento Lazy nesse campo para ele carregar só quando vc resgatar o campo com getter:

@Formula("(SELECT COUNT(endpro.endpro_id) FROM endereco e LEFT JOIN endereco_produto endpro ON e.end_id = endpro.end_id WHERE e.end_id = end_id)")  
@Basic(fetch=FetchType.LAZY) //Adiciona essa linha
private Long countEnderecoProduto;

Obs*: Esse tipo de questão está mais apropriada para o GUJ Respostas![/quote]
Obrigado pela resposta.
Não sabia desse método, nesse tempo que postei eu vi que tem como usar o setResultTransformer. Seria mal prática eu usá-lo ou tb é válido?
Estou usando assim:

query = getSession().createQuery("SELECT oo.estpro_etiqueta AS estpro_etiqueta, oo.estpro_dataproducao AS estpro_dataproducao, oo.estpro_id AS estpro_id, oo.estpro_op as estpro_op, oo.estpro_quantidade as estpro_quantidade, oo.pro_cod as pro_cod, oo.est_id as est_id FROM EstacionamentoProduto oo WHERE oo.est_id is not null"); query.setResultTransformer(Transformers.aliasToBean(EstacionamentoProduto.class));

Agora respondendo sobre o @Formula, eu tentei coloca-lo como LAZY LOADING, o problema é que ele não funciona com o @Formula. Eu até cheguei a ver algumas instruções pra conseguir fazer o LAZY funcionar no FORMULA, só que eu tentei e não consegui fazer funcionar, só dava pau no meu projeto (maven)

Valeu!

Não é má prática, só que da outra maneira vc não precisa utilizar o ResultTransformer, vc faz tudo de uma vez (Seleciona o objeto, popula o id e ja faz um cast com uniqueResult()), no caso do Lazy ele é meio chato de utilizar, porque vc precisa ter uma instancia persistente na session para trabalhar com ele, ou seja, faz um load/get do objeto e ai sim vc pode começar a trabalhar com ele!!

Entendi.
Em relação ao LAZY, eu ja uso ele, porém é o @Formula nativo que não funciona nele mesmo…

Bom, eu tive alguns problemas em utilizar o load, principalmente quando eu queria mesclar listas de objetos @ManyToOne, porque ele trazia um proxy do objeto ao invés do objeto concreto, também só de falar que houve um erro quando tentou implementar o Lazy é muito genérico, o certo é pegar o erro na stack, fazer o debug e entender o que acontece pra arranjar uma solução ou procurar saber sobre erro na documentação!

Na verdade não da erro nenhum, pois é o @Formula que não trabalha com Lazy loading, ele simplesmente não funciona…
Agora em relação ao que você falou, eu uso LEFT JOIN FETCH no hql para acabar com esse erro que voce teve…

Isso dai é uma funcionalidade do Hibernate, pra não ter que ir no banco toda hora ele procura o objeto procurado na sessão, se tiver ele retorna um proxy, pra resolver isso é só utilizar uma consulta normal com createQuery ou SQL ou fazer um get() que tem os mesmos parametros do load só que traz o objeto concreto!! Bom, esse seu erro do Lazy ai eu peguei um post do StackOverflow que mostra uma maneira de fazer isso (carregar com Lazy), mas parece que vc precisa de um plugin do maven pra tanto, da uma olhada, talvez seja util!