2009-08-31 30 views
11

¿Hay alguna forma de asignar una propiedad calculada mediante JPA?Asignación de propiedades calculadas con JPA

Suponiendo que tengo un objeto Invoice con uno o más InvoiceLineItems dentro de ella, quiero tener una propiedad persistente calculado sobre la clase Invoice que me da la cantidad total:

class Invoice { 
    ... 

    @Column(name = "TOTAL_AMOUNT") 
    public BigDecimal getTotalAmount() { 
     BigDecimal amount = BigDecimal.ZERO; 
     for (InvoiceLineItem lineItem : lineItems) { 
      amount = amount.add(lineItem.getTotalAmount()); 
     } 
     return amount; 
    } 
} 

Ahora, podría crear una método setTotalAmount protegido no-operativo setTotalAmount para hacer feliz a JPA, pero me preguntaba si hay una forma de hacerle saber a JPA que el mapeo es de una sola manera y para evitar crear un método setter superfluo.

Gracias, Aleks

Respuesta

9

Lo que he descrito no es una propiedad calculada en el sentido de la APP. Lo está calculando usted mismo dentro de su método: simplemente marque ese método como @Transient y JPA lo ignorará.

Si realmente necesita una propiedad calculada (donde "calculado" significa "calculado mediante expresión SQL"), tendrá que anotarlo de acuerdo con su proveedor de JPA. Para Hibernate que haría que a través de @Formula anotación:

@Formula("col1 * col2") 
public int getValue() { 
... 
} 

Otros proveedores pueden tener sus propias formas de configurar esto; no hay un estándar JPA.

+0

Marcado propiedad como @Transient no me ayudará. No quiero que JPA lo ignore: quiero que persista la cantidad total en una base de datos para poder consultarla directamente sin tener que agregar información de la tabla secundaria. Entonces, lo que estoy preguntando es cómo persistir una propiedad calculada (en el sentido de Java, sin relación con la persistencia) sin tener que implementar un setter innecesario para ella. –

+3

Tu ejemplo es bastante extraño entonces. Si ** está almacenando ** este valor y lo está consultando, ¿por qué está recalculando en su getter? La conclusión, sin embargo, es que si anota el método getter (en lugar de la propiedad) debe tener un setter correspondiente (puede ser privado) para que JPA puecle ese valor en su entidad. – ChssPly76

+0

El ejemplo que brindé es una simplificación excesiva del modelo de dominio con el que estoy trabajando, que tiene varios niveles de relaciones de uno a muchos, con una propiedad calculada en cada nivel que depende de los niños. Calcular el valor en Java según sea necesario es mucho más fácil que intentar actualizar el total a medida que se agregan, eliminan o modifican objetos secundarios en una jerarquía (profunda), por lo que lo estoy recalculando. –

4

Quizás la anotación PrePersist se puede usar para esto.

@Column(name = "TOTAL_AMOUNT") 
private BigDecimal totalAmount; 

@PrePersist 
public void updateTotalAmount() { 
    BigDecimal amount = BigDecimal.ZERO; 
    for (InvoiceLineItem lineItem : lineItems) { 
     amount = amount.add(lineItem.getTotalAmount()); 
    } 
    this.totalAmount = amount; 
} 
+0

Esto definitivamente es bueno saberlo, gracias Sin embargo, yo Necesito que el total se actualice cada vez que lo veo, no solo antes de que persista, entonces no funcionará en mi caso particular. –

+0

Braaaains ... Quiero decir, ¿por qué no tendrías un 'updateTotalAmount privado () ', y llamar eso desde el acccessor' getTotalAmount() ', así como' @ PrePersist'? ¿No es eso para lo que es un getter? –

5

Sé que estoy haciendo un necro -ing este hilo, pero tal vez podría ayudar a alguien.

Si desea calcular el valor de lectura, el @PostLoad anotación podría ser lo que quiere:

@Transient 
private BigDecimal totalAmount; 

@PostLoad 
public void onPostLoad() { 
    BigDecimal amount = BigDecimal.ZERO; 
    for (InvoiceLineItem lineItem : lineItems) { 
     amount = amount.add(lineItem.getTotalAmount()); 
    } 
    this.totalAmount = amount; 
} 
+1

No es realmente la respuesta a la pregunta de OPs, pero por cierto, solo el correcto responde a MI pregunta porque quiero algo ligeramente diferente del OP ... ¡Así que gracias por publicarlo aquí! +1 –

Cuestiones relacionadas