2011-11-20 15 views
14

Me gustaría agregar un campo Date/DateTime/Timestamp en un objeto de entidad, que se creará automáticamente cuando la entidad se cree/persista y se establezca en "ahora", para no volver a actualizarse nunca más.Cómo crear un campo de fecha/marca de tiempo generado automáticamente en una Play!/JPA?

Otros casos de uso incluyeron campos que siempre se actualizaron para contener la última fecha de modificación de la entidad.

Yo solía lograr tales requisitos in the mysql schema.

¿Cuál es la mejor manera de hacer esto en Play!/JPA?

+0

¿Tiene algún requisito que indique que se supone que la base de datos debe establecer el valor de la fecha 'actual' o puede hacerlo la JPA? –

+0

@PiotrNowicki - se puede hacer por JPA. Actualmente lo estoy haciendo dentro de mi código de aplicación. – ripper234

Respuesta

32

Hay un fragmento de código que puede adaptar para lograr lo que desea. Eche un vistazo:

// Timestampable.java 

package models; 

import java.util.Date; 

import javax.persistence.Column; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.MappedSuperclass; 
import javax.persistence.PrePersist; 
import javax.persistence.PreUpdate; 
import javax.persistence.Version; 

import play.db.ebean.Model; 

@MappedSuperclass 
public class Timestampable extends Model { 

    @Id 
    @GeneratedValue 
    public Long id; 

    @Column(name = "created_at") 
    public Date createdAt; 

    @Column(name = "updated_at") 
    public Date updatedAt; 

    @Version 
    public int version; 

    @Override 
    public void save() { 
    createdAt(); 
    super.save(); 
    } 

    @Override 
    public void update() { 
    updatedAt(); 
    super.update(); 
    } 

    @PrePersist 
    void createdAt() { 
    this.createdAt = this.updatedAt = new Date(); 
    } 

    @PreUpdate 
    void updatedAt() { 
    this.updatedAt = new Date(); 
    } 
} 
+0

Esto funcionó, gracias. Además de lo anterior, si no coloca la propiedad de columna @Column (name = "created_date", updatable = false) durante la actualización, será nulo. – Buminda

20

Creo que puede lograrlo en al menos dos formas.

valor por defecto de base de datos

Creo que la manera más fácil sería para marcar la columna como updateable=false, insertable=false (esto le dará la inmutabilidad - la APP no incluirá esta columna en INSERT y UPDATE declaraciones) y el establecimiento de la base de datos columna para tener un valor predeterminado de AHORA.

APP Ciclo de Vida de los métodos de devolución de llamada

Otra forma sería la de proporcionar un método de devolución de llamada de ciclo de vida @PrePersist que fijaría el objeto de fecha para la fecha real new Date(). Entonces necesitarás asegurarte de que nadie editará este valor, por lo que no debes proporcionar ningún setter para esta propiedad.

Si desea que la fecha se actualice cuando se modifique entidad, podría, de forma similar, implementar @PreUpdate método de devolución de llamada de ciclo de vida que establecería la fecha de modificación real.

Sólo recuerde que si se trabaja con objetos Date que debe hacer una copia defensiva de su fecha de objeto (por lo que debe devolver algo así como new Date(oldDate.getTime()); en lugar de llanura return oldDate).
Esto evitará que los usuarios usen getter de su Fecha y modifiquen su estado.

+0

¿Dónde marcaría la columna actualizable = falso, etc. ...? ¿Usando una anotación? Además, ¿por qué necesito una copia defensiva en getters? Getters no llamará 'save()' de todos modos, entonces ¿cómo puede cambiar el valor? – ripper234

+0

Sí, agregando la anotación '@ Column' en su campo de fecha (o haciendo en el archivo' orm.xml' si lo usa). El 'java.util.Date' es una clase mutable. El usuario puede obtenerlo usando getter, por lo que obtiene una referencia al campo Fecha de su clase. Puede invocar, por ejemplo, date.setTime (1) cambiando así el estado de la fecha. Entonces el JPA persistirá en su objeto de fecha que fue cambiado por el usuario. –

+0

JPA solo persistirá si llama 'save()' explícitamente. De todos modos, si por "usuarios" te refieres a "personas que pueden escribir código Java en mi proyecto", eso no es un problema para mí. Si se refería a los visitantes reales de mi sitio, no entiendo cómo pueden hacer algo para llamar a 'set' en el objeto de fecha. – ripper234

Cuestiones relacionadas