Propriedade calculada com JPA / Hibernate

Meu bean Java possui uma propriedade childCount. Esta propriedade não está mapeada para uma coluna do database . Em vez disso, ele deve ser calculado pelo database com uma function COUNT() operando na junit do meu bean Java e seus filhos. Seria ainda melhor se essa propriedade pudesse ser calculada sob demanda / “preguiçosamente”, mas isso não é obrigatório.

Na pior das hipóteses, posso definir a propriedade desse bean com HQL ou a API Criteria, mas preferiria não fazer isso.

A anotação do @Formula Hibernate pode ajudar, mas mal consegui encontrar qualquer documentação.

Qualquer ajuda muito apreciada. Obrigado.

O JPA não oferece nenhum suporte para a propriedade derivada, portanto você terá que usar uma extensão específica do provedor. Como você mencionou, o @Formula é perfeito para isso ao usar o Hibernate. Você pode usar um fragment SQL:

 @Formula("PRICE*1.155") private float finalPrice; 

Ou até mesmo consultas complexas em outras tabelas:

 @Formula("(select min(o.creation_date) from Orders o where o.customer_id = id)") private Date firstOrderDate; 

Onde id é o id da entidade atual.

A postagem do blog a seguir vale a pena ser lida: Hibernate Derived Properties – Performance and Portability .

Sem mais detalhes, não posso dar uma resposta mais precisa, mas o link acima deve ser útil.

Veja também:

  • Seção 5.1.22. Elementos de coluna e fórmula (documentação do Hibernate Core)
  • Seção 2.4.3.1. Fórmula (documentação de Anotações do Hibernate)

Conforme explicado neste artigo , você tem três opções:

  • você está calculando o atributo usando um método @Transient
  • você também pode usar o ouvinte de entidades @PostLoad
  • ou você pode usar a anotação @Formula específica do Hibernate

Enquanto o Hibernate permite que você use @Formula , com JPA, você pode usar o retorno de chamada @PostLoad para preencher uma propriedade transitória com o resultado de algum cálculo:

 @Column(name = "price") private Double price; @Column(name = "tax_percentage") private Double taxes; @Transient private Double priceWithTaxes; @PostLoad private void onLoad() { this.priceWithTaxes = price * taxes; } 

Para consultas mais complexas, você pode usar o @Formula do Hibernate, conforme explicado neste artigo :

 @Formula( "round(" + " (interestRate::numeric / 100) * " + " cents * " + " date_part('month', age(now(), createdOn)" + ") " + "/ 12) " + "/ 100::numeric") private double interestDollars;