Pregunta

Mi Java Bean tiene una propiedad de infancia. Esta propiedad es no mapeado a una columna de base de datos. En cambio, debería ser calculado por la base de datos con un COUNT() función Operando en la unión de mi Java Bean y sus hijos. Sería aún mejor si esta propiedad pudiera calcularse a pedido / "perezosamente", pero esto no es obligatorio.

En el peor de los casos, puedo establecer esta propiedad de Bean en HQL o la API de criterios, pero preferiría no hacerlo.

El hibernado @Formula La anotación puede ayudar, pero apenas pude encontrar documentación.

Cualquier ayuda muy apreciada. Gracias.

¿Fue útil?

Solución

JPA no ofrece ningún soporte para la propiedad derivada, por lo que tendrá que usar una extensión específica del proveedor. Como lo mencionaste, @Formula es perfecto para esto cuando se usa Hibernate. Puedes usar un fragmento SQL:

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

O incluso consultas complejas en otras tablas:

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

Dónde id es el id de la entidad actual.

Vale la pena leer la siguiente publicación del blog: Propiedades derivadas de hibernación: rendimiento y portabilidad.

Sin más detalles, no puedo dar una respuesta más precisa, pero el enlace anterior debería ser útil.

Ver también:

Otros consejos

Como se explica en Este artículo, tienes tres opciones:

  • o está calculando el atributo usando un @Transient método
  • también puedes usar @PostLoad escucha de la entidad
  • o puedes usar el hibernado específico @Formula anotación

Mientras que hibernate te permite usar @Fórmula, con JPA, puedes usar el @PostLoad devolución de llamada para poblar un transitorio propiedad con el resultado de algún 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 más complejas, puede usar el hibernado @Formula, como se explica en Este artículo:

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

Echa un vistazo a Vistas de entidad de perseveridad de incendio que funciona además de JPA y proporciona soporte de primera clase DTO. Puede proyectar cualquier cosa a los atributos dentro de las vistas de la entidad e incluso reutilizará los nodos de unión existentes para las asociaciones si es posible.

Aquí hay un ejemplo de mapeo

@EntityView(Order.class)
interface OrderSummary {
  Integer getId();
  @Mapping("SUM(orderPositions.price * orderPositions.amount * orderPositions.tax)")
  BigDecimal getOrderAmount();
  @Mapping("COUNT(orderPositions)")
  Long getItemCount();
}

Obtener esto generará una consulta JPQL/HQL similar a esta

SELECT
  o.id,
  SUM(p.price * p.amount * p.tax),
  COUNT(p.id)
FROM
  Order o
LEFT JOIN
  o.orderPositions p
GROUP BY
  o.id

Aquí hay una publicación de blog sobre proveedores de subconsulto personalizados que también podrían ser interesantes para usted: https://blazebit.com/blog/2017/entity-view-mapping-subqueries.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top