Hibernate 및 MySQL을 사용한 생성 타임 스탬프 및 마지막 업데이트 타임 스탬프


244

특정 최대 절전 모드 엔터티의 경우 생성 시간과 마지막 업데이트 시간을 저장해야합니다. 이것을 어떻게 설계 하시겠습니까?

  • 데이터베이스에서 어떤 데이터 유형을 사용 하시겠습니까 (MySQL, 아마도 다른 시간대의 JVM이라고 가정)? 데이터 유형이 시간대를 인식합니까?

  • 당신이 자바에서 어떤 데이터 유형을 사용 ( Date, Calendar, long, ...)?

  • 타임 스탬프 (데이터베이스, ORM 프레임 워크 (Hibernate) 또는 애플리케이션 프로그래머)를 설정하는 담당자는 누구입니까?

  • 매핑에 어떤 주석을 사용 @Temporal하시겠습니까 (예 :) ?

나는 작업 솔루션을 찾고있을뿐만 아니라 안전하고 잘 설계된 솔루션을 찾고 있습니다.

답변:


266

JPA 주석을 사용하는 경우 이벤트 후크를 사용 @PrePersist하여 다음을 수행 할 수 있습니다 @PreUpdate.

@Entity
@Table(name = "entities")    
public class Entity {
  ...

  private Date created;
  private Date updated;

  @PrePersist
  protected void onCreate() {
    created = new Date();
  }

  @PreUpdate
  protected void onUpdate() {
    updated = new Date();
  }
}

또는 @EntityListener클래스 에서 주석을 사용하고 이벤트 코드를 외부 클래스에 배치 할 수 있습니다 .


7
@PrePersist 및 @PerUpdate는 JPA 주석이므로 J2SE에서 아무런 문제없이 작동합니다.
Kdeveloper

2
@ Kumar-JPA 대신 일반 Hibernate 세션을 사용하는 경우 JPA 주석에 비해 매우 우아하고 컴팩트하지는 않지만 최대 절전 모드 이벤트 리스너를 사용해 볼 수 있습니다.
Shailendra

43
JPA 하나 현재 최대 절전 모드에서 "@CreationTimestamp"와 "@UpdateTimestamp"를 사용할 수 있습니다
플로리안 네스

@FlorianLoch Timestamp가 아닌 Date에 해당하는 것이 있습니까? 아니면 내 자신을 만들어야합니까?
mike

151

당신은 사용할 수 있습니다 @CreationTimestamp@UpdateTimestamp:

@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "create_date")
private Date createDate;

@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modify_date")
private Date modifyDate;

3
고마워요 그런 작은 일이 타임 스탬프를 업데이트해야합니다. 몰랐어요 당신은 내 하루를 구했다.
Virendra Sagar

TemporalType.DATE첫 번째 경우와 TemporalType.TIMESTAMP두 번째 경우 가 있습니다 .
v.ladynev

이것이 자동으로 값을 설정한다고 말하고 있습니까? 그건 내 경험이 아닙니다. 그것도 @CreationTimestamp있고 @UpdateTimestamp하나는 일부를 필요 @Column(..., columnDefinition = "timestamp default current_timestamp")로하거나 사용 @PrePersist하고 @PreUpdate(후자는 클라이언트가 다른 값을 설정할 수 없도록 멋지게 보장합니다).
Arjan

2
객체를 업데이트하고 유지하면 bd가 create_date를 잃어 버렸습니다 ... 왜?
Brenno Leal

1
제거 내 경우 임 nullable=false에서 @Column(name = "create_date" , nullable=false)근무
Shantaram TUPE

113

이 게시물의 리소스를 다른 소스에서 왼쪽과 오른쪽으로 가져온 정보와 함께이 우아한 솔루션과 함께 다음과 같은 추상 클래스를 만들었습니다.

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@MappedSuperclass
public abstract class AbstractTimestampEntity {

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created", nullable = false)
    private Date created;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated", nullable = false)
    private Date updated;

    @PrePersist
    protected void onCreate() {
    updated = created = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
    updated = new Date();
    }
}

다음과 같이 모든 엔티티를 확장하십시오.

@Entity
@Table(name = "campaign")
public class Campaign extends AbstractTimestampEntity implements Serializable {
...
}

5
엔터티 에 다른 배타적 동작 을 추가 할 때까지 (그리고 둘 이상의 기본 클래스를 확장 할 수 없을 때까지) 좋습니다. 기본 클래스는 AspectJ를가 ITD 또는 이벤트 리스너 @kieren 딕슨의 답변을 볼 수 있지만입니다하지 않고 동일한 효과를 얻을 수있는 유일한 방법을 AFAIK
gpilotino

3
전체 엔티티가 저장되지 않거나 외부 응용 프로그램 또는 수동 쿼리에 의해 수정 되더라도 여전히이 필드를 업데이트하도록 MySQL 트리거를 사용 하여이 작업을 수행합니다.
웹넷

3
예외가 발생하여 실례를 보여 주시겠습니까?not-null property references a null or transient value: package.path.ClassName.created
Sumit Ramteke

@rishiAgar, 아니에요. 그러나 지금은 기본 생성자에서 내 속성에 날짜를 할당했습니다. 내가 찾은 후에 알려 드리겠습니다.
Sumit Ramteke

1
@Column(name = "updated", nullable = false, insertable = false)작동하도록 변경하십시오 . 이 대답은 너무 많은 upvotes을 가지고 있다는 흥미로운 ..
표시 이름

20

1. 사용해야 할 데이터베이스 열 유형

첫 번째 질문은

데이터베이스에서 어떤 데이터 유형을 사용 하시겠습니까 (MySQL, 아마도 다른 시간대의 JVM이라고 가정)? 데이터 유형이 시간대를 인식합니까?

MySQL에서 TIMESTAMP열 유형은 JDBC 드라이버 로컬 시간대에서 데이터베이스 시간대로 이동하지만 최대 시간 소인까지만 타임 스탬프를 저장할 수 있습니다.'2038-01-19 03:14:07.999999 있으므로 향후 최선의 선택은 아닙니다.

따라서이 DATETIME상한을 갖지 않는 대신 사용 하는 것이 좋습니다 . 그러나 DATETIME시간대를 인식하지 못합니다. 따라서 데이터베이스 측면에서 UTC를 사용하고 hibernate.jdbc.time_zoneHibernate 속성을 사용하는 것이 가장 좋습니다 .

hibernate.jdbc.time_zone설정 에 대한 자세한 내용은 이 기사를 확인 하십시오 .

2. 어떤 엔티티 속성 유형을 사용해야합니까

두 번째 질문은 다음과 같습니다.

Java (Date, Calendar, long, ...)에서 어떤 데이터 유형을 사용 하시겠습니까?

Java 측에서는 Java 8을 사용할 수 있습니다 LocalDateTime. 레거시를 사용할 수도 Date있지만 Java 8 날짜 / 시간 유형은 변경 불가능하므로 더 좋으며 로깅 할 때 시간대를 로컬 시간대로 이동하지 않습니다.

Hibernate가 지원하는 Java 8 날짜 / 시간 유형에 대한 자세한 내용은 이 기사를 확인 하십시오 .

이제이 질문에 대답 할 수도 있습니다.

매핑에 어떤 주석을 사용 @Temporal하시겠습니까 (예 :) ?

당신은을 사용하는 경우 LocalDateTime또는 java.sql.Timestamp타임 스탬프 개체 속성을 매핑, 당신은 사용할 필요가 없습니다@Temporal Hibernate는 이미이 속성은 JDBC 타임 스탬프로 저장하는 것을 알고 있기 때문이다.

을 사용하는 경우에만 다음 과 같이 주석 java.util.Date을 지정해야합니다 @Temporal.

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_on")
private Date createdOn;

그러나 다음과 같이 매핑하면 훨씬 좋습니다.

@Column(name = "created_on")
private LocalDateTime createdOn;

감사 열 값을 생성하는 방법

세 번째 질문은 다음과 같습니다.

타임 스탬프 (데이터베이스, ORM 프레임 워크 (Hibernate) 또는 애플리케이션 프로그래머)를 설정하는 담당자는 누구입니까?

매핑에 어떤 주석을 사용 하시겠습니까 (예 : @Temporal)?

이 목표를 달성 할 수있는 방법은 여러 가지가 있습니다. 데이터베이스가 그렇게하도록 허용 할 수 있습니다.

를 들어 create_on열, 당신은 사용할 수 DEFAULT, DDL 제약을 같이 :

ALTER TABLE post 
ADD CONSTRAINT created_on_default 
DEFAULT CURRENT_TIMESTAMP() FOR created_on;

를 들어 updated_on열, 당신과 함께 열 값을 설정하는 DB 트리거를 사용할 수 있습니다CURRENT_TIMESTAMP() 주어진 행이 수정 될 때마다.

또는 JPA 또는 Hibernate를 사용하여 설정하십시오.

다음과 같은 데이터베이스 테이블이 있다고 가정합니다.

감사 열이있는 데이터베이스 테이블

그리고 각 테이블에는 다음과 같은 열이 있습니다.

  • created_by
  • created_on
  • updated_by
  • updated_on

최대 절전 모드 @CreationTimestamp@UpdateTimestamp주석 사용

최대 절전 모드는 및 열 을 매핑하는 데 사용할 수있는 @CreationTimestamp@UpdateTimestamp주석을 제공합니다 .created_onupdated_on

@MappedSuperclass모든 엔티티에 의해 확장 될 기본 클래스를 정의하는 데 사용할 수 있습니다 .

@MappedSuperclass
public class BaseEntity {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "created_on")
    @CreationTimestamp
    private LocalDateTime createdOn;

    @Column(name = "created_by")
    private String createdBy;

    @Column(name = "updated_on")
    @UpdateTimestamp
    private LocalDateTime updatedOn;

    @Column(name = "updated_by")
    private String updatedBy;

    //Getters and setters omitted for brevity
}

그리고 모든 엔티티는 다음 BaseEntity과 같이 확장됩니다 .

@Entity(name = "Post")
@Table(name = "post")
public class Post extend BaseEntity {

    private String title;

    @OneToMany(
        mappedBy = "post",
        cascade = CascadeType.ALL,
        orphanRemoval = true
    )
    private List<PostComment> comments = new ArrayList<>();

    @OneToOne(
        mappedBy = "post",
        cascade = CascadeType.ALL,
        orphanRemoval = true,
        fetch = FetchType.LAZY
    )
    private PostDetails details;

    @ManyToMany
    @JoinTable(
        name = "post_tag",
        joinColumns = @JoinColumn(
            name = "post_id"
        ),
        inverseJoinColumns = @JoinColumn(
            name = "tag_id"
        )
    )
    private List<Tag> tags = new ArrayList<>();

    //Getters and setters omitted for brevity
}

사용에 대한 자세한 내용은 이 문서를@MappedSuperclass 확인 하십시오 .

그러나,해도 createdOnupdateOn속성이 최대 절전 모드 전용으로 설정 @CreationTimestamp하고 @UpdateTimestamp주석의 createdByupdatedBy 다음 JPA 용액에 의해 도시 된 바와 같이, 애플리케이션 콜백 등록을 필요로한다.

JPA 사용 @EntityListeners

감사 속성을 Embeddable에 캡슐화 할 수 있습니다.

@Embeddable
public class Audit {

    @Column(name = "created_on")
    private LocalDateTime createdOn;

    @Column(name = "created_by")
    private String createdBy;

    @Column(name = "updated_on")
    private LocalDateTime updatedOn;

    @Column(name = "updated_by")
    private String updatedBy;

    //Getters and setters omitted for brevity
}

AuditListener감사 속성을 설정하려면을 만듭니다 .

public class AuditListener {

    @PrePersist
    public void setCreatedOn(Auditable auditable) {
        Audit audit = auditable.getAudit();

        if(audit == null) {
            audit = new Audit();
            auditable.setAudit(audit);
        }

        audit.setCreatedOn(LocalDateTime.now());
        audit.setCreatedBy(LoggedUser.get());
    }

    @PreUpdate
    public void setUpdatedOn(Auditable auditable) {
        Audit audit = auditable.getAudit();

        audit.setUpdatedOn(LocalDateTime.now());
        audit.setUpdatedBy(LoggedUser.get());
    }
}

를 등록 AuditListener하기 위해 @EntityListenersJPA 주석을 사용할 수 있습니다 .

@Entity(name = "Post")
@Table(name = "post")
@EntityListeners(AuditListener.class)
public class Post implements Auditable {

    @Id
    private Long id;

    @Embedded
    private Audit audit;

    private String title;

    @OneToMany(
        mappedBy = "post",
        cascade = CascadeType.ALL,
        orphanRemoval = true
    )
    private List<PostComment> comments = new ArrayList<>();

    @OneToOne(
        mappedBy = "post",
        cascade = CascadeType.ALL,
        orphanRemoval = true,
        fetch = FetchType.LAZY
    )
    private PostDetails details;

    @ManyToMany
    @JoinTable(
        name = "post_tag",
        joinColumns = @JoinColumn(
            name = "post_id"
        ),
        inverseJoinColumns = @JoinColumn(
            name = "tag_id"
        )
    )
    private List<Tag> tags = new ArrayList<>();

    //Getters and setters omitted for brevity
}

JPA로 감사 속성을 구현하는 방법에 대한 자세한 내용은 이 문서를@EntityListener 확인 하십시오 .


매우 철저한 답변, 감사합니다. 나는 선호하는 것에 반대 datetime한다 timestamp. 데이터베이스가 타임 스탬프의 시간대를 알기를 원합니다. 표준 시간대 변환 오류를 방지합니다.
Ole VV

timestsmp유형은 시간대 정보를 저장하지 않습니다. 앱 TZ에서 DB TZ 로의 대화 만 수행합니다. 실제로, UI를 렌더링하기 전에 클라이언트 TZ를 별도로 저장하고 애플리케이션에서 대화를 수행하려고합니다.
Vlad Mihalcea

옳은. MySQL timestamp은 항상 UTC입니다. MySQL TIMESTAMP은 저장을 위해 현재 시간대에서 UTC 로 값을 변환 하고 검색을 위해 UTC에서 현재 시간대로 다시 변환 합니다. MySQL 설명서 : DATE, DATETIME 및 TIMESTAMP 유형
Ole VV

17

인터셉터를 사용하여 값을 설정할 수도 있습니다

엔티티가 구현하는 TimeStamped라는 인터페이스를 작성하십시오.

public interface TimeStamped {
    public Date getCreatedDate();
    public void setCreatedDate(Date createdDate);
    public Date getLastUpdated();
    public void setLastUpdated(Date lastUpdatedDate);
}

인터셉터 정의

public class TimeStampInterceptor extends EmptyInterceptor {

    public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, 
            Object[] previousState, String[] propertyNames, Type[] types) {
        if (entity instanceof TimeStamped) {
            int indexOf = ArrayUtils.indexOf(propertyNames, "lastUpdated");
            currentState[indexOf] = new Date();
            return true;
        }
        return false;
    }

    public boolean onSave(Object entity, Serializable id, Object[] state, 
            String[] propertyNames, Type[] types) {
            if (entity instanceof TimeStamped) {
                int indexOf = ArrayUtils.indexOf(propertyNames, "createdDate");
                state[indexOf] = new Date();
                return true;
            }
            return false;
    }
}

그리고 세션 팩토리에 등록하십시오



EntityManager 대신 SessionFactory로 작업하는 경우 이것이 하나의 솔루션입니다!
olivmir

이 맥락에서와 비슷한 문제를 겪고있는 사람들을 위해 : 엔티티 가이 여분의 필드를 직접 정의하지 않고 (createdAt, ...) 부모 클래스에서 상속하는 경우이 부모 클래스에 주석을 달아야합니다 @MappedSuperclass-그렇지 않으면 Hibernate는이 필드들을 찾지 못한다.
olivmir

17

Olivier의 솔루션을 사용하면 업데이트 문 중에 다음과 같은 문제가 발생할 수 있습니다.

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException : 'created'열은 null 일 수 없습니다.

이 문제를 해결하려면 "작성된"속성의 @Column 주석에 updatable = false를 추가하십시오.

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", nullable = false, updatable=false)
private Date created;

1
우리는를 사용하고 @Version있습니다. 엔티티가 설정되면 두 개의 호출이 이루어지며 하나는 저장하고 다른 하나는 업데이트합니다. 이 때문에 같은 문제에 직면했습니다. 추가 @Column(updatable = false)하면 문제가 해결 되었습니다 .
Ganesh Satpute

12

도와 주신 모든 분들께 감사드립니다. 나 자신에게 약간의 연구를 한 후에 (나는 질문을 한 사람입니다), 여기 내가 가장 이해하는 것이 있습니다.

  • 데이터베이스 열 유형 : 1970 년 이후 시간대에 관계없이 밀리 초 ( decimal(20)2 초) 는 2 자리 64 개에 20 자리가 있고 디스크 공간이 저렴하기 때문에 나타납니다 . 솔직 해지자 또한, DEFAULT CURRENT_TIMESTAMP트리거도 사용하지 않습니다. 나는 DB에서 마술을 원하지 않는다.

  • Java 필드 유형 : long. Unix 타임 스탬프는 다양한 라이브러리에서 잘 지원되며 longY2038 문제가 없으며 타임 스탬프 산술이 빠르고 쉽습니다 (주로 연산자 <와 연산자 +는 일 / 월 / 년이 계산에 관여하지 않는다고 가정). 그리고 가장 중요한 것은, 프리미티브 longjava.lang.Longs 모두 s와 달리 불변 이며 (가치에 의해 효과적으로 전달됨) java.util.Date; foo.getLastUpdate().setTime(System.currentTimeMillis())다른 사람의 코드를 디버깅 할 때 와 같은 것을 찾기 위해 정말로 화가 났을 것 입니다.

  • ORM 프레임 워크는 데이터를 자동으로 채울 책임이 있습니다.

  • 나는 이것을 아직 테스트하지는 않았지만 내가 할 것이라고 생각하는 문서 만보 고있다 @Temporal. @Version이 목적으로 사용할 수 있는지 확실하지 않습니다 . @PrePersist@PreUpdate수동으로 제어하는 좋은 대안이다. 모든 엔티티에 대한 레이어 슈퍼 타입 (공통 기본 클래스)에 그 추가, 당신이 정말로 위해 타임 스탬프를 원하는 귀여운 아이디어가 제공되며 모든 당신의 엔티티.


long과 Long은 변경 불가능하지만 설명 된 상황에서는 도움이되지 않습니다. 그들은 여전히 ​​foo.setLastUpdate (new Long (System.currentTimeMillis ());라고 말할 수 있습니다.
Ian McLaird

2
괜찮아. Hibernate는 어쨌든 setter를 필요로한다 (또는 리플렉션을 통해 필드에 직접 접근하려고 시도 할 것이다). 애플리케이션 코드에서 타임 스탬프를 수정하는 사람을 추적하는 데 어려움을 겪고있었습니다. getter를 사용하여 할 수 있으면 까다 롭습니다.
ngn

ORM 프레임 워크가 날짜를 자동으로 채울 책임이 있다는 귀하의 주장에 동의하지만 한 단계 더 나아가 날짜는 클라이언트가 아닌 데이터베이스 서버의 시계에서 설정해야한다고 말합니다. 이것이이 목표를 달성했는지 확실하지 않습니다. SQL에서는 sysdate 함수를 사용 하여이 작업을 수행 할 수 있지만 Hibernate 또는 JPA 구현 에서이 작업을 수행하는 방법을 모르겠습니다.
MiguelMunoz 2016

나는 DB에서 마술을 원하지 않는다. 나는 당신이 무슨 뜻인지 알지만, 데이터베이스가 나쁜 / 새로운 / 우둔한 개발자로부터 스스로를 보호해야한다는 사실을 고려하고 싶습니다. 대기업에서는 데이터 무결성이 매우 중요합니다. 다른 사람에게 의존하여 좋은 데이터를 삽입 할 수는 없습니다. 제약 조건, 기본값 및 FK가이를 달성하는 데 도움이됩니다.
Icegras

6

세션 API를 사용하는 경우이 답변 에 따라 PrePersist 및 PreUpdate 콜백이 작동하지 않습니다 .

내 코드에서 Hibernate Session의 persist () 메소드를 사용하고 있으므로이 작업을 수행 할 수있는 유일한 방법은 아래 코드를 사용 하고이 블로그 게시물 ( 답변에 게시 됨)을 따르는 입니다.

@MappedSuperclass
public abstract class AbstractTimestampEntity {

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created")
    private Date created=new Date();

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated")
    @Version
    private Date updated;

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getUpdated() {
        return updated;
    }

    public void setUpdated(Date updated) {
        this.updated = updated;
    }
}

같은 복제 된 개체를 반환해야 updated.clone()그렇지 않으면 다른 구성 요소가 내부 상태 (날짜) 조작 할 수 있습니다
1ambda


3

다음 코드가 나를 위해 일했습니다.

package com.my.backend.models;

import java.util.Date;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import com.fasterxml.jackson.annotation.JsonIgnore;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import lombok.Getter;
import lombok.Setter;

@MappedSuperclass
@Getter @Setter
public class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Integer id;

    @CreationTimestamp
    @ColumnDefault("CURRENT_TIMESTAMP")
    protected Date createdAt;

    @UpdateTimestamp
    @ColumnDefault("CURRENT_TIMESTAMP")
    protected Date updatedAt;
}

안녕하세요, 테스트 클래스에서 사용할 수 없기 때문에 일반적으로 부모 클래스에서 protected Integer id;와 같이 왜 필요 protected.getId()
shareef

2

좋은 접근 방식은 모든 엔티티에 공통 기본 클래스를 사용하는 것입니다. 이 기본 클래스에서는 모든 엔티티 (공통 디자인), 작성 및 최종 업데이트 날짜 특성에 공통적으로 이름이 지정된 경우 id 특성을 가질 수 있습니다.

작성 날짜의 경우 단순히 java.util.Date 특성을 유지하십시오 . 항상 new Date ()로 초기화하십시오 .

마지막 업데이트 필드의 경우 타임 스탬프 속성을 사용할 수 있으며 @Version으로 매핑해야합니다. 이 주석을 사용하면 Hibernate에 의해 속성이 자동으로 업데이트됩니다. 최대 절전 모드도 낙관적 잠금을 적용합니다 (좋은 일임).


2
낙관적 잠금에 타임 스탬프 열을 사용하는 것은 좋지 않습니다. 항상 정수 버전 열을 사용하십시오. 이유는 2 개의 JVM이 다른 시간에 있고 밀리 초 정확도를 갖지 않을 수 있습니다. 대신 최대 절전 모드에서 DB 타임 스탬프를 사용하면 DB에서 추가로 선택해야합니다. 대신 버전 번호를 사용하십시오.
sethu

2

강화하기 위해 : java.util.CalenderTimestamps 용이 아닙니다 . java.util.Date시간대와 같은 지역적 요소에 관계없이 잠시 동안입니다. 대부분의 데이터베이스는 이런 방식으로 물건을 저장합니다 (보이지 않는 경우에도; 이것은 일반적으로 클라이언트 소프트웨어의 시간대 설정이며 데이터는 양호합니다)


1

JAVA의 데이터 유형으로 java.util.Date를 사용하는 것이 좋습니다. 캘린더를 사용할 때 꽤 불쾌한 시간대 문제가 발생했습니다. 이 스레드를 참조하십시오 .

타임 스탬프를 설정하려면 AOP 방식을 사용하거나 테이블에서 트리거를 사용할 수 있습니다 (실제로는 이것이 트리거 사용이 허용되는 유일한 방법 임).


1

시간을 DateTime 및 UTC로 저장하는 것을 고려할 수 있습니다. MySql은 데이터를 저장하고 검색 할 때 날짜를 UTC로 변환하고 현지 시간으로 다시 변환한다는 사실 때문에 일반적으로 Timestamp 대신 DateTime을 사용합니다. 차라리 그런 종류의 논리를 한곳에 유지하고 싶습니다 (비즈니스 계층). 그래도 타임 스탬프를 사용하는 것이 바람직한 다른 상황이 있다고 확신합니다.


1

우리도 비슷한 상황에 처해있었습니다. 우리는 Mysql 5.7을 사용하고있었습니다.

CREATE TABLE my_table (
        ...
      updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    );

이것은 우리를 위해 일했습니다.


데이터베이스에서 직접 SQL 쿼리에 의해 데이터가 수정되는 경우에도 작동합니다. @PrePersist그리고 @PrePersist이러한 경우에는 적용되지 않습니다.
pidabrow

1

@Transactional을 사용하는 경우메소드에서 을 하는 경우 @CreationTimestamp 및 @UpdateTimestamp는 DB에 값을 저장하지만 save (...)를 사용한 후 null을 반환합니다.

이 상황에서 saveAndFlush (...)를 사용하여 트릭을 수행했습니다.


0

Java 코드 에서이 작업을 수행하지 않아야한다고 생각합니다 .MySql 테이블 정의에서 열 기본값을 간단히 설정할 수 있습니다. 여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.