Настройка столбца временной метки JPA, который будет генерироваться базой данных?
-
03-07-2019 - |
Вопрос
В моей базе данных SQL Server 2000 у меня есть столбец timestamp (в функции, а не в типе данных) типа DATETIME
названный lastTouched
установлено значение getdate()
в качестве значения по умолчанию / привязки.
Я использую классы сущностей JPA, сгенерированные Netbeans 6.5, и это есть в моем коде
@Basic(optional = false)
@Column(name = "LastTouched")
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;
Однако, когда я пытаюсь поместить объект в базу данных, я получаю,
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.generic.Stuff.lastTouched
Я пробовал настраивать @Basic
Для (optional = true)
, но это выдает исключение, в котором говорится, что база данных не позволяет null
значения для TIMESTAMP
колонка, которой у него нет по замыслу.
ERROR JDBCExceptionReporter - Cannot insert the value NULL into column 'LastTouched', table 'DatabaseName.dbo.Stuff'; column does not allow nulls. INSERT fails.
Ранее я заставлял это работать в чистом режиме гибернации, но я переключился на JPA и понятия не имею, как сообщить ему, что предполагается, что этот столбец сгенерирован на стороне базы данных.Обратите внимание, что я все еще использую Hibernate в качестве своего уровня сохранения JPA.
Решение
Я исправил проблему, изменив код на
@Basic(optional = false)
@Column(name = "LastTouched", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;
Таким образом, столбец метки времени игнорируется при создании вставок SQL. Не уверен, что это лучший способ сделать это. Обратная связь приветствуется.
Другие советы
Я понимаю, что это немного поздно, но я успешно аннотировал столбец метки времени с помощью
@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
Это также должно работать с CURRENT_DATE
и CURRENT_TIME
. Я использую JPA / Hibernate с Oracle, поэтому YMMV.
@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;
это сработало для меня. больше информации
У меня это хорошо работает с использованием JPA2.0 и MySQL 5.5.10, для случаев, когда меня волнует только последний раз, когда была изменена строка. MySQL создаст отметку времени при первой вставке, и каждый раз при вызове UPDATE в строке. (ПРИМЕЧАНИЕ: это будет проблематично, если мне будет интересно, действительно ли ОБНОВЛЕНИЕ внесло изменения).
" отметка времени " столбец в этом примере подобен «последнему прикосновению»; column.x` р>
В приведенном ниже коде используется отдельный столбец " версия " для оптимистичной блокировки. Р>
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;
}
(ПРИМЕЧАНИЕ: @Version не работает со столбцом MySQL «DATETIME», где тип атрибута «Дата» в классе Entity. Это произошло потому, что Date генерировал значение с точностью до миллисекунды, однако MySQL не сохранял миллисекунду, поэтому, когда он сравнивал то, что было в базе данных, и «присоединенный» объект, он думал, что у них разные номера версий)
Из руководства MySQL относительно TIMESTAMP :
With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
Я не думаю, что каждая база данных имеет временные метки автоматического обновления (напримерPostgres).Поэтому я решил обновить это поле вручную везде в своем коде.Это будет работать с любой базой данных:
thingy.setLastTouched(new Date());
HibernateUtil.save(thingy);
Есть причины использовать триггеры, но для большинства проектов это не одна из них.Триггеры погружают вас еще глубже в конкретную реализацию базы данных.
MySQL 5.6.28 (Ubuntu 15.10, 64-разрядная версия OpenJDK 1.8.0_66) кажется очень снисходительным, не требующим ничего сверх
@Column(name="LastTouched")
MySQL 5.7.9 (CentOS 6, 64-разрядная версия OpenJDK 1.8.0_72) работает только с
@Column(name="LastTouched", insertable=false, updatable=false)
нет:
FAILED: removing @Temporal
FAILED: @Column(name="LastTouched", nullable=true)
FAILED: @Column(name="LastTouched", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
Моя другая системная информация (идентичная в обеих средах)
- переход в спящий режим-entitymanager 5.0.2
- переход в спящий режим-валидатор 5.2.2
- mysql-соединитель-java 5.1.38
@Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
@Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;`enter code here`