Установка столбца временной отметки 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.
Ответы
Ответ 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'