Настройка столбца временной метки JPA, который будет генерироваться базой данных?

StackOverflow https://stackoverflow.com/questions/811845

Вопрос

В моей базе данных 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`
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top