데이터베이스에서 생성 할 JPA 타임 스탬프 열을 설정 하시겠습니까?
-
03-07-2019 - |
문제
내 SQL Server 2000 데이터베이스에는 타임 스탬프 (데이터 유형이 아닌 함수)가 있습니다. DATETIME
명명 된 lastTouched
로 설정 getdate()
기본값/바인딩으로.
NetBeans 6.5 생성 JPA 엔티티 클래스를 사용하고 있으며 내 코드에이를 가지고 있습니다.
@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로 전환 되었으며이 열이 데이터베이스 측면에서 생성 될 것이라고 생각하는 방법을 알지 못했습니다. 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
. Oracle과 함께 JPA/Hibernate를 사용하고 있습니다.
@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;
이것은 나를 위해 효과가있었습니다.더 많은 정보
마지막으로 행이 수정 된 경우에만 관심이있는 경우 JPA2.0 및 MySQL 5.5.10을 사용 하여이 작업이 잘 작동합니다. MySQL은 첫 번째 삽입시 타임 스탬프를 생성하며 매번 업데이트가 행으로 호출됩니다. (참고 : 업데이트가 실제로 변경되었는지 여부를 걱정하면 문제가됩니다).
이 예제의 "타임 스탬프"열은 "마지막 터치"열과 같습니다 .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은 Entity 클래스에서 속성 유형이 "날짜"인 MySQL "DateTime"열에서 작동하지 않습니다. 날짜는 밀리 초까지 값을 생성했지만 MySQL은 밀리 초를 저장하지 않았기 때문입니다. , 데이터베이스에있는 것과 "첨부 된"엔티티를 비교했을 때 버전 번호가 다른 것으로 생각했습니다)
With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
나는 모든 데이터베이스에 자동 업데이트 타임 스탬프 (예 : 우편둥이)가 있다고 생각하지 않습니다. 그래서 나는이 필드를 내 코드의 어느 곳에서나 수동으로 업데이트하기로 결정했습니다. 이것은 모든 데이터베이스에서 작동합니다.
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")
내 다른 시스템 정보 (두 환경 모두 동일)
- 최대 절전 모드-엔티티 관리자 5.0.2
- 최대 절전 모드 검증기 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`