Pergunta

No meu banco de dados SQL Server 2000, eu tenho um timestamp (em função não no tipo de dados) coluna do tipo DATETIME chamado lastTouched conjunto para getdate() como seu valor default / vinculativo.

Eu estou usando o NetBeans 6.5 classes de entidade JPA geradas, e ter isso em meu código

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

No entanto, quando eu tento colocar o objeto no banco de dados eu recebo,

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

Eu tentei definindo a opção @Basic para (optional = true), mas que lança uma exceção dizendo que o banco de dados não permite valores null para a coluna TIMESTAMP, o que não acontece por design.

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

Eu já tenho isso para o trabalho em puro Hibernate, mas tenho sentido comutada para JPA e não têm idéia de como dizer-se que esta coluna é suposto ser gerado no lado do banco de dados. Note que eu ainda estou usando Hibernate como meu JPA persistência camada.

Foi útil?

Solução

Eu corrigiu o problema alterando o código para

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

Assim, a coluna timestamp é ignorado quando a geração de inserções SQL. Não tenho certeza se esta é a melhor maneira de fazer isto. O feedback é bem-vindo.

Outras dicas

Sei que isso é um pouco tarde, mas eu tive sucesso com anotação de uma coluna timestamp com

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

Isso também deve trabalhar com CURRENT_DATE e CURRENT_TIME. Eu estou usando JPA / Hibernate com a Oracle, assim YMMV.

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

Isso funcionou para mim. mais informações

Eu tenho essa JPA2.0 funcionando bem usando e MySQL 5.5.10, para os casos em que só se preocupam com a última vez que a linha foi modificada. MySQL irá criar um timestamp na primeira inserção, e cada atualização de tempo é chamado na linha. (NOTA: esta vai ser problemático se eu me importava se ou não o UPDATE realmente fez uma mudança).

A coluna "timestamp" neste exemplo é como uma "última tocado" column.x`

O código abaixo usa uma coluna de "versão" separado para bloqueio otimista.

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 não funciona em uma coluna de MySQL "DATETIME", onde o tipo de atributo é "Data" na classe Entity Isso porque Data estava gerando um valor baixo para o milissegundo, no entanto MySQL não foi armazenar o milissegundo, por isso, quando ele fez uma comparação entre o que estava no banco de dados, e a entidade "anexo", que pensavam que tinham diferentes números de versão)

partir do manual MySQL sobre TIMESTAMP :

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

Eu não acho que cada banco de dados tem data e hora de atualização automática (por exemplo, Postgres). Então eu decidi atualizar este campo manualmente em todos os lugares no meu código. Isto irá trabalhar com cada banco de dados:

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

Há razões para gatilhos de uso, mas para a maioria dos projetos, isso não é um deles. Gatilhos cavar-lhe ainda mais em uma implementação de banco de dados específico.

MySQL 5.6 0,28 (Ubuntu 15.10, OpenJDK 64-Bit 1.8.0_66) parece ser muito indulgente, não necessitando de qualquer coisa além

@Column(name="LastTouched")

MySQL 5.7 .9 fortes (Red Hat Enterprise Linux 6, OpenJDK 64-Bit 1.8.0_72) funciona apenas com

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

não

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

O meu outras informações do sistema (idêntico em ambos os ambientes)

  • hibernate-entitymanager 5.0.2
  • hibernate-validador 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top