manytoone insertar ejemplo datos con java jpa persistence annotations timestamp

java - insertar - Establecer una columna de marca de tiempo JPA para ser generada por la base de datos?



insertar datos con jpa (5)

En mi base de datos de SQL Server 2000, tengo una columna de fecha y hora (en la función no en el tipo de datos) del tipo DATETIME denominada lastTouched set to getdate() como valor / enlace predeterminado.

Estoy usando las clases de entidades JPA generadas por Netbeans 6.5, y tengo esto en mi código

@Basic(optional = false) @Column(name = "LastTouched") @Temporal(TemporalType.TIMESTAMP) private Date lastTouched;

Sin embargo, cuando trato de poner el objeto en la base de datos que obtengo,

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.generic.Stuff.lastTouched

He intentado configurar el @Basic como (optional = true) , pero eso arroja una excepción que dice que la base de datos no permite valores null para la columna TIMESTAMP , lo que no hace por diseño.

ERROR JDBCExceptionReporter - Cannot insert the value NULL into column ''LastTouched'', table ''DatabaseName.dbo.Stuff''; column does not allow nulls. INSERT fails.

Anteriormente conseguí que esto funcionara en Hibernate puro, pero tengo sentido cambiar a JPA y no tengo idea de cómo decir que se supone que esta columna se generará en el lado de la base de datos. Tenga en cuenta que todavía estoy usando Hibernate como mi capa de persistencia JPA.


Esto funciona bien usando JPA2.0 y MySQL 5.5.10, para casos en los que solo me importa la última vez que se modificó la fila. MySQL creará una marca de tiempo en la primera inserción, y cada vez que se llame a UPDATE en la fila. (NOTA: esto será problemático si me importa si la ACTUALIZACIÓN realmente hizo un cambio).

La columna "timestamp" en este ejemplo es como una columna "last-touched" .x`

El siguiente código utiliza una columna "versión" para el bloqueo optimista.

private long version; private Date timeStamp @Version public long getVersion() { return version; } public void setVersion(long version) { this.version = version; } // columnDefinition could simply be = "TIMESTAMP", as the other settings are the MySQL default @Column(name="timeStamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") @Temporal(TemporalType.TIMESTAMP) public Date getTimeStamp() { return timeStamp; } public void setTimeStamp(Date timeStamp) { this.timeStamp = timeStamp; }

(NOTA: @Version no funciona en una columna MySQL "DATETIME", donde el tipo de atributo es "Fecha" en la clase Entity. Esto se debía a que Date generaba un valor menor al milisegundo, aunque MySQL no almacenaba el milisegundo , entonces cuando hizo una comparación entre lo que estaba en la base de datos y la entidad "adjunta", pensó que tenían diferentes números de versión)

Del manual de MySQL con respecto a TIMESTAMP :

With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.


Me doy cuenta de que esto es un poco tarde, pero he tenido éxito anotando una columna de marca de tiempo con

@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")

Esto también debería funcionar con CURRENT_DATE y CURRENT_TIME . Estoy usando JPA / Hibernate con Oracle, entonces YMMV.


No creo que cada base de datos tenga marcas de tiempo de actualización automática (por ejemplo, Postgres). Así que decidí actualizar este campo de forma manual en todas partes de mi código. Esto funcionará con todas las bases de datos:

thingy.setLastTouched(new Date()); HibernateUtil.save(thingy);

Hay razones para usar disparadores, pero para la mayoría de los proyectos, este no es uno de ellos. Los disparadores lo excavan aún más en una implementación de base de datos específica.

MySQL 5.6 .28 (Ubuntu 15.10, OpenJDK 64-Bit 1.8.0_66) parece ser muy indulgente, no requiere nada más allá

@Column(name="LastTouched")

MySQL 5.7 .9 (CentOS 6, OpenJDK 64-Bit 1.8.0_72) solo funciona con

@Column(name="LastTouched", insertable=false, updatable=false)

no:

FAILED: removing @Temporal FAILED: @Column(name="LastTouched", nullable=true) FAILED: @Column(name="LastTouched", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")

Mi otra información del sistema (idéntica en ambos entornos)

  • hibernate-entitymanager 5.0.2
  • hibernate-validator 5.2.2
  • mysql-connector-java 5.1.38

Solucioné el problema cambiando el código a

@Basic(optional = false) @Column(name = "LastTouched", insertable = false, updatable = false) @Temporal(TemporalType.TIMESTAMP) private Date lastTouched;

Por lo tanto, la columna de marca de tiempo se ignora al generar inserciones SQL. No estoy seguro de si esta es la mejor manera de hacerlo. Comentarios son bienvenidos.


@Column(nullable = false, updatable = false) @CreationTimestamp private Date created_at;

esto funcionó para mí. más información