Pregunta

En mi base de datos SQL Server 2000, tengo una columna de marca de tiempo (en función no en el tipo de datos) del tipo DATETIME llamado lastTouched establecido en getdate () como su valor / enlace predeterminado.

Estoy usando las clases de entidad 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 @Basic en (opcional = true) , pero eso arroja una excepción que dice que la base de datos no permite nulo valores para la columna TIMESTAMP , que no lo 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 decirle 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.

¿Fue útil?

Solución

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 si esta es la mejor manera de hacerlo. Los comentarios son bienvenidos.

Otros consejos

Me doy cuenta de que esto es un poco tarde, pero he tenido éxito al anotar 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, así que YMMV.

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

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

Tengo esto funcionando bien usando JPA2.0 y MySQL 5.5.10, para los casos en 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 llama a UPDATE en la fila. (NOTA: esto será problemático si me preocupa si la ACTUALIZACIÓN realmente hizo un cambio).

La " marca de tiempo " la columna en este ejemplo es como un " último tocado " column.x`

El código siguiente utiliza una columna separada " 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 Entidad. Esto se debía a que Date estaba generando un valor hasta el milisegundo, sin embargo, MySQL no almacenaba el milisegundo, así que 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 relacionado con TIMESTAMP :

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

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

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

Hay razones para usar desencadenadores, pero para la mayoría de los proyectos, este no es uno de ellos. Los desencadenadores le permiten profundizar 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á de

@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
@Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
@Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;`enter code here`
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top