Подтвердить что ты не робот

Установка столбца временной отметки JPA для создания базы данных?

В моей базе данных 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.

Я раньше получил это, чтобы работать в чистом Hibernate, но у меня есть смысл переключиться на JPA и не знаю, как сказать, что этот столбец предполагается сгенерировать на стороне базы данных. Обратите внимание, что я все еще использую Hibernate в качестве уровня сохраняемости JPA.

4b9b3361

Ответ 1

Я исправил проблему, изменив код на

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

Таким образом, столбцы timestamp игнорируются при генерации SQL-вставок. Не уверен, что это лучший способ сделать это. Обратная связь приветствуется.

Ответ 2

Я понимаю, что это немного поздно, но у меня был успех с аннотированием столбца timestamp с

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

Это также должно работать с CURRENT_DATE и CURRENT_TIME. Я использую JPA/Hibernate с Oracle, поэтому YMMV.

Ответ 3

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

это сработало для меня. больше информации

Ответ 4

У меня это хорошо работает с использованием JPA2.0 и MySQL 5.5.10, для случаев, когда я только забочусь о последнем изменении строки. MySQL будет создавать временную метку при первой вставке и каждый раз, когда UPDATE вызывается в строке. (ПРИМЕЧАНИЕ: это будет проблематично, если я забочусь, действительно ли UPDATE произвело изменение).

Столбец "timestamp" в этом примере похож на "last-touched" 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 не работает в столбце "DATETIME" MySQL, где тип атрибута - "Дата" в классе Entity. Это было потому, что дата генерировала значение до миллисекунды, однако MySQL не был сохраняя миллисекунду, поэтому, когда он проводил сравнение между тем, что было в базе данных, и "прикрепленной" сущностью, он думал, что у них разные номера версий)

Из руководства MySQL относительно TIMESTAMP:

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

Ответ 5

Я не думаю, что каждая база данных имеет автоматическое обновление временных меток (например, Postgres). Поэтому я решил обновить это поле вручную везде в своем коде. Это будет работать с каждой базой данных:

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

Есть причины использовать триггеры, но для большинства проектов это не один из них. Триггеры копают вас еще глубже в конкретной реализации базы данных.

MySQL 5.6.28 (Ubuntu 15.10, OpenJDK 64-бит 1.8.0_66), кажется, очень прощает, не требуя ничего кроме

@Column(name="LastTouched")

MySQL 5.7.9 (CentOS 6, OpenJDK 64-бит 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")

Моя другая информация о системе (идентична в обеих средах)

  • hibernate-entitymanager 5.0.2
  • hibernate-validator 5.2.2
  • mysql-connector-java 5.1.38

Ответ 6

У меня это хорошо работает, используя JPA 2.0 и MySQL 5.5.10.

Я вставил поле Timesamp следующим образом:

@Column(name = "LastTouched")
private Timestamp lastTouched;

Ответ 7

@Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
@Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;'enter code here'