Domanda

Nel mio database di SQL Server 2000, ho una colonna timestamp (in funzione non nel tipo di dati) di tipo DATETIME denominato lastTouched impostato su getdate () come valore / associazione predefinito.

Sto usando le classi di entità JPA generate da Netbeans 6.5 e ho questo nel mio codice

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

Tuttavia quando provo a inserire l'oggetto nel database ottengo,

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

Ho provato a impostare @Basic su (opzionale = vero) , ma questo genera un'eccezione dicendo che il database non consente null valori per la colonna TIMESTAMP , che non è in base alla progettazione.

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

In precedenza avevo fatto in modo che funzionasse in puro Hibernate, ma ho senso passare a JPA e non ho idea di come dirlo che questa colonna dovrebbe essere generata sul lato del database. Nota che sto ancora usando Hibernate come livello di persistenza JPA.

È stato utile?

Soluzione

Ho risolto il problema modificando il codice in

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

Quindi la colonna timestamp viene ignorata quando si generano inserimenti SQL. Non sono sicuro se questo è il modo migliore per farlo. Il feedback è il benvenuto.

Altri suggerimenti

Mi rendo conto che è un po 'tardi, ma ho avuto successo con l'annotazione di una colonna timestamp con

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

Questo dovrebbe funzionare anche con CURRENT_DATE e CURRENT_TIME . Sto usando JPA / Hibernate con Oracle, quindi YMMV.

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

questo ha funzionato per me. maggiori informazioni

Funziono bene con JPA2.0 e MySQL 5.5.10, per i casi in cui mi interessa solo l'ultima volta che la riga è stata modificata. MySQL creerà un timestamp al primo inserimento e ogni volta che UPDATE viene chiamato sulla riga. (NOTA: questo sarà problematico se mi importasse se l'AGGIORNAMENTO abbia effettivamente apportato una modifica).

Il " timestamp " la colonna in questo esempio è come un "ultimo tocco" column.x`

Il codice seguente utilizza una colonna " versione " separate per un bloccaggio ottimistico.

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 non funziona su una colonna MySQL "DATETIME", in cui il tipo di attributo è "Data" nella classe Entity. Questo perché Date stava generando un valore fino al millisecondo, tuttavia MySQL non stava memorizzando il millisecondo, quindi quando ha fatto un confronto tra ciò che era nel database e l'entità "collegata", pensava di avere numeri di versione diversi)

Dal manuale di MySQL relativo a TIMESTAMP :

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

Non credo che ogni database abbia i timestamp di aggiornamento automatico (ad esempio Postgres). Quindi ho deciso di aggiornare questo campo manualmente ovunque nel mio codice. Funzionerà con ogni database:

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

Esistono motivi per utilizzare i trigger, ma per la maggior parte dei progetti, questo non è uno di questi. I trigger consentono di approfondire ulteriormente l'implementazione di un database specifico.

MySQL 5.6 .28 (Ubuntu 15.10, OpenJDK 64-Bit 1.8.0_66) sembra essere molto indulgente, non richiede nulla oltre

@Column(name="LastTouched")

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

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

non

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

Altre mie informazioni di sistema (identiche in entrambi gli ambienti)

  • hibernate-entitymanager 5.0.2
  • hibernate-validator 5.2.2
  • mysql-connettore-java 5.1.38
@Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
@Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;`enter code here`
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top