Hazırda Beklet ve MySQL ile oluşturma zaman damgası ve son güncelleme zaman damgası


244

Belirli bir Hazırda Bekletme varlığı için, oluşturma süresini ve en son ne zaman güncellendiğini saklama gereksinimimiz vardır. Bunu nasıl tasarlarsınız?

  • Veritabanında hangi veri türlerini kullanırsınız (MySQL varsayalım, muhtemelen JVM'den farklı bir saat diliminde)? Veri türleri saat diliminde farkında olacak mı?

  • Eğer Java hangi veri türleri kullanırsınız ( Date, Calendar, long, ...)?

  • Zaman damgalarını (veritabanı, ORM çerçevesi (Hazırda Bekletme) veya uygulama programcısı) ayarlamaktan kim sorumludur?

  • Eşleme için hangi ek açıklamaları kullanırsınız (örn. @Temporal)?

Sadece çalışan bir çözüm değil, güvenli ve iyi tasarlanmış bir çözüm arıyorum.

Yanıtlar:


266

JPA ek açıklamalarını kullanıyorsanız @PrePersistve @PreUpdateolay kancalarını şunları yapabilirsiniz :

@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();
  }
}

ya @EntityListenerda sınıftaki ek açıklamayı kullanabilir ve olay kodunu harici bir sınıfa yerleştirebilirsiniz.


7
@PrePersist ve @PerUpdate JPA ek açıklamaları olduğundan J2SE'de sorunsuz çalışır.
Kdeveloper

2
@Kumar - Düz Hazırda Bekletme oturumu (JPA yerine) kullanıyorsanız, hazırda bekletme olayı dinleyicilerini deneyebilirsiniz, ancak bu çok zarif ve kompakt ve JPA ek açıklamalarına karşı değildir.
Shailendra

43
Şu anda JPA ile Hazırda Bekletme modunda "@CreationTimestamp" ve "@UpdateTimestamp" kullanılabilir
Florian Loch

@FlorianLoch, Tarih için Zaman Damgası yerine bir eşdeğeri var mı? Yoksa kendiminkini yaratmak zorunda mıyım?
mike

151

Sadece kullanabilir @CreationTimestampve @UpdateTimestamp:

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

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

3
teşekkürler bro böyle küçük bir şey güncelleme zaman damgası gerekir. Bilmiyordum. günümü kurtardın.
Virendra Sagar

Orada TemporalType.DATEbirinci durumda ve TemporalType.TIMESTAMPikinci birinde.
v.ladynev

Bunun değerleri otomatik olarak ayarladığını mı söylüyorsunuz? Bu benim deneyimim değil; hatta görünüyor @CreationTimestampve @UpdateTimestampbirinin ya biraz ihtiyacı var ya @Column(..., columnDefinition = "timestamp default current_timestamp")da @PrePersistve @PreUpdate(ikincisi de farklı bir değer ayarlayamıyor güzel sağlamak).
Arjan

2
Nesneyi güncellediğimde ve devam ettirdiğimde bd create_date dosyasını kaybetti ... neden?
Brenno Leal

1
Çıkarmadan davamı Im nullable=falsegelen @Column(name = "create_date" , nullable=false)çalıştı
Shantaram Tupe

113

Bu yazıdaki kaynakları farklı kaynaklardan sola ve sağa alarak, bu zarif çözümle geldim, aşağıdaki soyut sınıfı yarattım

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();
    }
}

ve tüm varlıklarınızın genişletmesini sağlayın, örneğin:

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

5
bu, varlıklarınıza farklı özel davranışlar eklemek istediğinize kadar iyidir (ve birden fazla temel sınıfı genişletemezsiniz). afaik bir temel sınıf olmadan aynı etkiyi elde etmenin tek yolu enjektif itd veya olay dinleyicileri görmek @kieren dixon cevap
gpilotino

3
Tam varlık kaydedilmemiş veya herhangi bir harici uygulama veya manuel sorgu tarafından değiştirilse bile, yine de bu alanları güncelleyecek şekilde bir MySQL tetikleyicisi kullanarak yapardım.
Webnet

3
bana herhangi bir çalışma örneği verebilir misin çünkü istisna not-null property references a null or transient value: package.path.ClassName.created
yaşıyorum

@rishiAgar, Hayır, yok. Ama şimdilik mülküme varsayılan kurucudan tarih ataıyorum. Bulduğumda size haber vereceğim.
Sumit Ramteke

1
@Column(name = "updated", nullable = false, insertable = false)Çalışması için olarak değiştirin . İlginçtir ki bu cevap çok fazla oy aldı ..
displayname

20

1. Hangi veritabanı sütun türlerini kullanmalısınız?

İlk sorunuz:

Veritabanında hangi veri türlerini kullanırsınız (MySQL varsayalım, muhtemelen JVM'den farklı bir saat diliminde)? Veri türleri saat diliminde farkında olacak mı?

MySQL'de, TIMESTAMPsütun türü JDBC sürücüsü yerel saat diliminden veritabanı saat dilimine geçer, ancak yalnızca zaman damgalarını depolayabilir'2038-01-19 03:14:07.999999 , bu nedenle gelecek için en iyi seçim değildir.

Bu nedenle, DATETIMEbunun üst sınır sınırlaması olmayan daha iyi kullanım . Ancak, DATETIMEsaat dilimi farkında değildir. Bu nedenle, veritabanı tarafında UTC kullanmak ve hibernate.jdbc.time_zoneHibernate özelliğini kullanmak en iyisidir .

Ayarla ilgili daha fazla ayrıntı için bu makaleyehibernate.jdbc.time_zone göz atın .

2. Hangi varlık özelliği türünü kullanmalısınız?

İkinci sorunuz:

Java'da hangi veri türlerini kullanırsınız (Tarih, Takvim, uzun, ...)?

Java tarafında, Java 8'i kullanabilirsiniz LocalDateTime. Mirası da kullanabilirsiniz Date, ancak Java 8 Tarih / Saat türleri değiştirilemez olduklarından daha iyidir ve bunları kaydederken yerel saat dilimine kayma yapmazlar.

Hazırda Bekletme tarafından desteklenen Java 8 Tarih / Saat türleri hakkında daha fazla bilgi için bu makaleye göz atın .

Şimdi bu soruya da cevap verebiliriz:

Eşleme için hangi ek açıklamaları kullanırsınız (örn. @Temporal)?

Bir zaman damgası varlık özelliğini eşlemek için LocalDateTimeveya tuşunu kullanıyorsanız,java.sql.Timestamp@Temporal HIbernate bu özelliğin JDBC Zaman Damgası olarak kaydedileceğini zaten bildiği .

Yalnızca kullanıyorsanız ek açıklamayı şu java.util.Dateşekilde belirtmeniz gerekir @Temporal:

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

Ancak, bu şekilde eşleştirmeniz çok daha iyidir:

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

Denetim sütunu değerleri nasıl oluşturulur?

Üçüncü sorunuz:

Zaman damgalarını (veritabanı, ORM çerçevesi (Hazırda Bekletme) veya uygulama programcısı) ayarlamaktan kim sorumludur?

Eşleme için hangi ek açıklamaları kullanırsınız (örn. @Temporal)?

Bu hedefe ulaşmanın birçok yolu vardır. Veritabanının bunu yapmasına izin verebilirsiniz.

create_onSütun için aşağıdakiler DEFAULTgibi bir DDL kısıtlaması kullanabilirsiniz :

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

İçin updated_onsütunda, sizinle sütun değerini ayarlamak için bir DB tetiği kullanabilirsinizCURRENT_TIMESTAMP() belirli bir satır her değiştirildiğinde zaman.

Veya bunları ayarlamak için JPA veya Hazırda Beklet'i kullanın.

Aşağıdaki veritabanı tablolarına sahip olduğunuzu varsayalım:

Denetim sütunlarına sahip veritabanı tabloları

Ve her tabloda aşağıdaki gibi sütunlar bulunur:

  • created_by
  • created_on
  • updated_by
  • updated_on

Hazırda Beklet @CreationTimestampve@UpdateTimestamp ek açıklamaları

Hazırda Beklet @CreationTimestampve @UpdateTimestampile eşleştirmek için kullanılabilecek ek açıklamaları created_onveupdated_on sütunlarını .

@MappedSuperclassTüm varlıklar tarafından genişletilecek bir temel sınıf tanımlamak için kullanabilirsiniz :

@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
}

Ve tüm varlıklar şu şekilde genişletilir 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
}

Kullanımı hakkında daha fazla bilgi için bu makaleye@MappedSuperclass göz atın .

Bununla birlikte, olsa bile createdOnve updateOnözellikleri hazırda-spesifik tarafından ayarlanır @CreationTimestampve @UpdateTimestampek açıklamalar createdByve updatedByaşağıdaki JPA çözeltisi ile gösterildiği gibi, bir uygulama geri arama kayıt gerektirmektedir.

JPA kullanma @EntityListeners

Denetim özelliklerini Yerleştirilebilir öğeye ekleyebilirsiniz:

@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
}

Ve AuditListenerdenetim özelliklerini ayarlamak için bir oluşturun :

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());
    }
}

Kaydolmak için JPA ek açıklamasını AuditListenerkullanabilirsiniz @EntityListeners:

@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 ile denetim mülkleri uygulama hakkında daha fazla bilgi için bu makaleye@EntityListener göz atın .


Çok kapsamlı bir cevap, teşekkürler. Ben tercih konusunda hemfikir datetimeüzerinde timestamp. Veritabanınızın zaman damgalarınızın saat dilimini bilmesini istiyorsunuz. Bu, saat dilimi dönüştürme hatalarını önler.
Ole VV

timestsmpTip saat dilimi bilgisi saklamaz. Sadece uygulama TZ DB TZ bir konuşma yapar. Gerçekte, kullanıcı TZ'sini oluşturmadan önce istemci TZ'yi ayrı olarak saklamak ve konuşmayı uygulamada yapmak istiyorsunuz.
Vlad Mihalcea

Doğru. MySQL timestampher zaman UTC'dir. MySQL, TIMESTAMPdeğerleri geçerli saat diliminden UTC'ye UTC'ye ve UTC'den geçerli saat dilimine geri almak için dönüştürür. MySQL belgeleri: DATE, DATETIME ve TIMESTAMP Türleri
Ole VV

17

Değerleri ayarlamak için bir önleme aracı da kullanabilirsiniz

Varlıklarınızın uyguladığı TimeStamped adında bir arayüz oluşturun

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

Durdurucu tanımlayın

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;
    }
}

Ve bunu oturum fabrikasına kaydedin


1
Çalışır, teşekkürler. Tamamlayıcı bilgiler docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/…
Andrii Nemchenko

EntityManager yerine SessionFactory ile çalışıyorsanız bu bir çözümdür!
olivmir

Sadece bu bağlamda yaptığım gibi benzer bir sorunla karşı karşıya olanlar için: Varlığınızın kendisi bu ekstra alanları tanımlamıyorsa (createAt, ...) ancak bir üst sınıftan miras alırsa, bu üst sınıfın açıklanması gerekir @MappedSuperclass ile - aksi takdirde Hazırda Beklet bu alanları bulamaz.
olivmir

17

Olivier çözümü ile, güncelleme bildirimleri sırasında aşağıdakilerle karşılaşabilirsiniz:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 'Oluşturuldu' sütunu boş olamaz

Bunu çözmek için, "oluşturulan" özelliğinin @Column ek açıklamasına updatable = false ifadesini ekleyin:

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

1
Biz kullanıyoruz @Version. Bir varlık ayarlandığında, biri kaydetmek diğeri ise güncellemek üzere iki çağrı yapılır. Bu yüzden aynı sorunla karşı karşıyaydım. Eklediğimde @Column(updatable = false)sorunumu çözdüm.
Ganesh Satpute

12

Yardım eden herkese teşekkürler. Kendim biraz araştırma yaptıktan sonra (soruyu soran adamım), işte en anlamlı bulduğum şey:

  • Veritabanı sütun türü: 1970'ten bu yana saat dilimi-agnostik milisaniye sayısı, decimal(20)2 ^ 64'ün 20 hanesi olduğu ve disk alanı ucuz olduğu için temsil edilir ; açık sözlü olalım. Ayrıca, ne kullanacağım ne DEFAULT CURRENT_TIMESTAMPde tetikleyicileri kullanacağım . DB'de sihir istemiyorum.

  • Java alan türü: long. Unix zaman damgası çeşitli kütüphanelerde iyi desteklenir, longY2038 problemi yoktur, zaman damgası aritmetiği hızlı ve kolaydır (esas olarak operatör <ve operatör +, hesaplamalara gün / ay / yıl dahil olmadığı varsayılarak). Ve en önemlisi, s'nin aksine hem ilkel longs hem de java.lang.Longs değişmezdirjava.util.Date ; foo.getLastUpdate().setTime(System.currentTimeMillis())Başka birinin kodunda hata ayıklama gibi bir şey bulmak için gerçekten sinirli olurdu .

  • ORM çerçevesi, verilerin otomatik olarak doldurulmasından sorumlu olmalıdır.

  • Bunu henüz test etmedim, ama sadece @Temporalişi yapacağını düşündüğüm belgelere baktığımda ; @Versionbu amaçla kullanıp kullanamayacağımdan emin değilim . @PrePersistve @PreUpdatemanuel olarak kontrol etmek için iyi alternatiflerdir. Tüm varlıklar için katman süpertip (ortak temel sınıf) bu ekleme, gerçekten için Timestamping istediğiniz şirin bir fikir sağlanan olduğu bütün senin varlıkların.


Uzun ve Uzunlar değişmez olsa da, tarif ettiğiniz durumda size yardımcı olmaz. Yine de foo.setLastUpdate (yeni Uzun (System.currentTimeMillis ())
diyebilirler

2
Bu iyi. Hazırda bekletme modu ayarlayıcıyı yine de gerektirir (veya alana doğrudan yansıma yoluyla erişmeye çalışır). Uygulama kodumuzdaki zaman damgasını kimin değiştirdiğini takip etmekte zorluk çekiyordum. Bir alıcı kullanarak bunu yapmak zor.
ngn

ORM çerçevesinin tarihi otomatik olarak doldurmaktan sorumlu olması gerektiğini iddia ediyorum, ancak bir adım daha ileri gideceğim ve tarihin istemci yerine veritabanı sunucusunun saatinden ayarlanması gerektiğini söyleyebilirim. Bunun bu hedefe ulaşıp ulaşmadığı net değil. Sqdate işlevini kullanarak sql bunu yapabilirim, ancak Hibernate veya herhangi bir JPA uygulamasında bunu nasıl yapacağımı bilmiyorum.
MiguelMunoz

DB'de sihir istemiyorum. Ne demek istediğini anlıyorum, ama veritabanının kendisini kötü / yeni / clueless geliştiricilere karşı koruması gerektiğini düşünmek istiyorum. Veri bütünlüğü büyük bir şirkette çok önemlidir, iyi veri eklemek için başkalarına güvenemezsiniz. Kısıtlamalar, varsayılanlar ve FK'ler bunu başarmaya yardımcı olacaktır.
Icegras

6

Oturum API'sını kullanıyorsanız PrePersist ve PreUpdate geri çağrıları bu yanıta göre çalışmaz .

Kodumda Hibernate Session'ın persist () yöntemini kullanıyorum, bu yüzden bu işi yapabilmenin tek yolu aşağıdaki kodla ve bu blog gönderisini takip etmekti (ayrıca cevaba gönderildi ).

@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()Başka bileşenler gibi klonlanmış nesneleri döndürmelidir iç durumunu (tarih) manipüle edebilir
1ambda


3

Aşağıdaki kod benim için çalıştı.

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;
}

Merhaba, neden genel protected Integer id;olarak protectedana sınıfta olduğu gibi ihtiyacımız var , çünkü test durumlarımda kullanamadım.getId()
shareef

2

İyi bir yaklaşım, tüm varlıklarınız için ortak bir taban sınıfına sahip olmaktır. Bu temel sınıfta, tüm varlıklarınızda (ortak bir tasarım) yaygın olarak adlandırılmışsa, id özelliğiniz, oluşturma ve son güncelleme tarihi özellikleriniz olabilir.

Oluşturma tarihi için bir java.util.Date özelliğini tutmanız yeterlidir . Her zaman yeni Tarih () ile başlattığınızdan emin olun .

Son güncelleme alanı için bir Timestamp özelliği kullanabilirsiniz, @Version ile eşlemeniz gerekir. Bu Ek Açıklama ile mülk Hazırda Beklet tarafından otomatik olarak güncellenir. Hibernate'in de iyimser kilitleme uygulayacağına dikkat edin (bu iyi bir şeydir).


2
iyimser kilitleme için bir zaman damgası sütunu kullanmak kötü bir fikirdir. Her zaman bir tamsayı sürüm sütunu kullanın. Nedeni, 2 JVM farklı zamanlarda olabilir ve milisaniye doğruluğuna sahip olmayabilir. Bunun yerine hazırda bekletme modunu DB zaman damgasını kullanırsanız, DB'den ek seçimler anlamına gelir. Bunun yerine sadece sürüm numarasını kullanın.
sethu

2

Sadece güçlendirmek için: java.util.CalenderZaman damgaları için değil . java.util.Datebir an için, zaman dilimleri gibi bölgesel şeylerden bağımsızdır. Çoğu veritabanı işleri bu şekilde saklar (görünmüyor olsalar bile; bu genellikle istemci yazılımında bir saat dilimi ayarıdır; veriler iyidir)


1

JAVA veri türü olarak kesinlikle java.util.Date kullanmanızı öneririz. Takvim'i kullanırken oldukça kötü saat dilimi sorunlarıyla karşılaştım. Bu Konuyu Gör .

Zaman damgalarını ayarlamak için ya bir AOP yaklaşımı kullanmanızı tavsiye ederim ya da sadece tablodaki Tetikleyicileri kullanabilirsiniz (aslında bu şimdiye kadar tetikleyicilerin kullanımını kabul edilebilir bulduğum tek şey).


1

Saati DateTime olarak ve UTC'de depolamayı düşünebilirsiniz. MySql, tarihleri ​​depolarken ve alırken tarihleri ​​UTC'ye ve yerel saate geri dönüştürdüğü için genellikle DateTime yerine Timestamp kullanıyorum. Bu tür mantıklardan herhangi birini tek bir yerde tutmayı tercih ederim (İş katmanı). Zaman damgasının kullanılmasının tercih edildiği başka durumlar olduğundan eminim.


1

Benzer bir durum yaşadık. Mysql 5.7 kullanıyorduk.

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

Bu bizim için işe yaradı.


Ayrıca, verilerin doğrudan veritabanındaki bir SQL sorgusu tarafından değiştirildiği bir durumda da çalışır. @PrePersistve @PrePersistböyle bir vakayı kapsamaz.
pidabrow

1

Biz kullanıyorsanız @Transactional bizim yöntemlerde, @CreationTimestamp ve @UpdateTimestamp (...) DB değer kazandıracak ancak tasarruf kullandıktan sonra null adlı dönecektir.

Bu durumda, saveAndFlush (...) kullanmak hile yaptı


0

Bence Java kodunda bunu yapmaz daha temiz, sadece MySql tablo tanımında sütun varsayılan değerini ayarlayabilirsiniz. resim açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.