হাইবারনেট এবং মাইএসকিউএল সহ টাইমস্ট্যাম্প এবং সর্বশেষ আপডেটের টাইমস্ট্যাম্প তৈরি করুন


244

একটি নির্দিষ্ট হাইবারনেট সত্তার জন্য আমাদের এটির তৈরির সময় এবং শেষ বার এটি আপডেট করা হয়েছিল store আপনি কিভাবে এটি ডিজাইন করবেন?

  • আপনি ডাটাবেসে কোন ডেটা প্রকারগুলি ব্যবহার করবেন (মাইএসকিউএল ধরে নিচ্ছেন, সম্ভবত জেভিএম ভিন্ন টাইম জোনে)? ডাটা টাইপগুলি কি টাইমজোন সচেতন হবে?

  • কি ধরনের তথ্য আপনি জাভা ব্যবহার করেন ( Date, Calendar, long, ...)?

  • টাইমস্ট্যাম্পগুলি সেট করার জন্য আপনি কাকে দায়বদ্ধ করবেন — ডাটাবেস, ওআরএম কাঠামো (হাইবারনেট), বা অ্যাপ্লিকেশন প্রোগ্রামার?

  • ম্যাপিংয়ের জন্য আপনি কোন টিকা ব্যবহার করবেন (উদাঃ @Temporal)?

আমি কেবল একটি কাজের সমাধান খুঁজছি না, তবে একটি নিরাপদ এবং সুনির্দিষ্ট সমাধানের সন্ধান করছি।

উত্তর:


266

আপনি যদি জেপিএ টিকা ব্যবহার করেন তবে আপনি এটি করতে পারেন @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
জে 2 এস-এ কোনও সমস্যা ছাড়াই কাজ করে, কারণ @ প্রিপার্সিস্ট এবং @ পেরু আপডেট জেপিএ টিকা।
কেডেভোপার

2
@ কুমার - আপনি যদি সরল হাইবারনেট অধিবেশন ব্যবহার করছেন (জেপিএ পরিবর্তে) আপনি ইভেন্ট শ্রোতাদের হাইবারনেট চেষ্টা করতে পারেন, যদিও এটি জেপিএ টিকা বনাম খুব মার্জিত এবং কমপ্যাক্ট নয়।
শৈলেন্দ্র

43
জেপিএর সাথে বর্তমান হাইবারনেটে "@CreationTimestamp" এবং "@UpdateTimestamp" ব্যবহার করতে পারবেন
ফ্লোরিয়ান লচ

@ ফ্লোরিয়ানলচ কি টাইমস্ট্যাম্পের চেয়ে ডেটের সমতুল্য? নাকি আমার নিজের তৈরি করতে হবে?
মাইক

150

আপনি কেবল ব্যবহার করতে পারেন @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
ধন্যবাদ ভাই যেমন একটি ছোট জিনিস টাইমস্ট্যাম্প আপডেট করা প্রয়োজন। আমি জানতাম না। তুমি আমার দিন বাঁচিয়েছ
বীরেন্দ্র সাগর

নেই TemporalType.DATEপ্রথম ক্ষেত্রে এবং TemporalType.TIMESTAMPদ্বিতীয় হবে।
v.ladynev

আপনি কি বলছেন এটি স্বয়ংক্রিয়ভাবে মানগুলি সেট করে? এটা আমার অভিজ্ঞতা নয়; এটি এমনকি এটির সাথে মনে হয় @CreationTimestampএবং এর @UpdateTimestampজন্য কিছু দরকার হয় @Column(..., columnDefinition = "timestamp default current_timestamp"), বা ব্যবহার করতে হবে @PrePersistএবং @PreUpdate(আধুনিকতার সাথে ক্লায়েন্টরা কোনও আলাদা মান নির্ধারণ করতে পারে না তা নিশ্চিত করে)।
আরজান

2
আমি যখন অবজেক্টটি আপডেট করি এবং এটি অবিরত রাখি, তখন বিডি ক্রিয়েট_ডেট হারিয়েছে ... কেন?
ব্রেন্নো লিয়াল

1
আমি আমার মামলাটি কাজ nullable=falseথেকে সরিয়ে দিচ্ছি@Column(name = "create_date" , nullable=false)
শান্তারাম টুপে

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
যতক্ষণ না আপনি নিজের সত্তাগুলিতে আলাদা একচেটিয়া আচরণ যুক্ত করতে চান (এবং আপনি একাধিক বেস শ্রেণি প্রসারিত করতে পারবেন না) এটি ভাল। বেস ক্লাস ব্যতীত আফাইক একই প্রভাব অর্জনের একমাত্র উপায় যদিও দিকনির্দেশনা বা ইভেন্ট শ্রোতারা @ কিরেইন ডিক্সন উত্তরটি দেখুন
gpilotino

3
আমি এটি একটি মাইএসকিউএল ট্রিগার ব্যবহার করে করব যাতে সম্পূর্ণ সত্তা সংরক্ষণ না হয় বা কোনও বাহ্যিক অ্যাপ্লিকেশন বা ম্যানুয়াল ক্যোয়ারী দ্বারা পরিবর্তিত হয়ে থাকে তবে এটি এখনও এই ক্ষেত্রগুলিকে আপডেট করবে।
ওয়েবনেট

3
আপনি কি আমাকে কোনও কাজের উদাহরণ দিতে পারেন কারণ আমি ব্যতিক্রম অনুভব করছিnot-null property references a null or transient value: package.path.ClassName.created
সুমিত রামতেকে

@ৃষিআগর, না আমার নেই। তবে আপাতত আমি ডিফল্ট কনস্ট্রাক্টর থেকে আমার সম্পত্তিটির জন্য তারিখ নির্ধারণ করেছি। আমি একবার খুঁজে পেয়েছি আপনাকে জানাতে হবে।
সুমিত রামতেকে

1
@Column(name = "updated", nullable = false, insertable = false)এটি কাজ করতে এটি পরিবর্তন করুন । আকর্ষণীয় যে এই উত্তর এত upvotes পেয়েছিলাম ..
displayname

20

1. আপনার কী ডাটাবেস কলাম ব্যবহার করা উচিত

আপনার প্রথম প্রশ্নটি ছিল:

আপনি ডাটাবেসে কোন ডেটা প্রকারগুলি ব্যবহার করবেন (মাইএসকিউএল ধরে নিচ্ছেন, সম্ভবত জেভিএম ভিন্ন টাইম জোনে)? ডাটা টাইপগুলি কি টাইমজোন সচেতন হবে?

মাইএসকিউএলে, TIMESTAMPকলামের ধরণটি জেডিবিসি ড্রাইভার স্থানীয় সময় অঞ্চল থেকে ডাটাবেস টাইমজোনকে স্থানান্তরিত করে, তবে এটি কেবল টাইমস্ট্যাম্পগুলি সঞ্চয় করতে পারে '2038-01-19 03:14:07.999999, সুতরাং এটি ভবিষ্যতের পক্ষে সেরা পছন্দ নয়।

সুতরাং এর DATETIMEপরিবর্তে আরও ভাল ব্যবহার করুন, যার উপরের সীমানাটির সীমাবদ্ধতা নেই। তবে DATETIMEটাইমজোন সচেতন নয়। সুতরাং, এই কারণে, ইউটিসি ডাটাবেস সাইডে ব্যবহার করা এবং hibernate.jdbc.time_zoneহাইবারনেট সম্পত্তি ব্যবহার করা ভাল ।

hibernate.jdbc.time_zoneসেটিং সম্পর্কে আরও তথ্যের জন্য , এই নিবন্ধটি দেখুন

২. কী সত্তা সম্পত্তি প্রকার আপনি ব্যবহার করা উচিত

আপনার দ্বিতীয় প্রশ্নটি ছিল:

আপনি জাভাতে কোন ডেটা টাইপ ব্যবহার করবেন (তারিখ, ক্যালেন্ডার, দীর্ঘ, ...)?

জাভা সাইডে, আপনি জাভা 8 ব্যবহার করতে পারেন LocalDateTime। আপনি উত্তরাধিকারটিও ব্যবহার করতে পারেন Date, তবে জাভা 8 তারিখ / সময়ের ধরণগুলি অপরিবর্তনীয় হওয়ার কারণে আরও ভাল এবং লগ ইন করার সময় কোনও টাইমজোন স্থানীয় সময় অঞ্চলে স্থানান্তরিত করবেন না।

হাইবারনেট দ্বারা সমর্থিত জাভা 8 তারিখ / সময়ের ধরণ সম্পর্কে আরও তথ্যের জন্য, এই নিবন্ধটি দেখুন

এখন, আমরা এই প্রশ্নের উত্তরও দিতে পারি:

ম্যাপিংয়ের জন্য আপনি কোন টিকা ব্যবহার করবেন (উদাঃ @Temporal)?

আপনি যদি টাইমস্ট্যাম্প সত্তা সম্পত্তিটি ব্যবহার করতে LocalDateTimeবা java.sql.Timestampমানচিত্রের জন্য ব্যবহার করে থাকেন তবে আপনার @Temporalএইচআইবারনেট ইতিমধ্যে জানে যে এই সম্পত্তিটি জেডিবিসি টাইমস্ট্যাম্প হিসাবে সংরক্ষণ করা উচিত knows

কেবলমাত্র আপনি যদি ব্যবহার করছেন তবে আপনার এটিকে টীকাটি java.util.Dateনির্দিষ্ট করতে হবে @Temporal:

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

তবে আপনি যদি এটির মতো ম্যাপ করেন তবে এটি আরও ভাল:

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

অডিট কলামের মানগুলি কীভাবে উত্পন্ন করা যায়

আপনার তৃতীয় প্রশ্নটি ছিল:

টাইমস্ট্যাম্পগুলি সেট করার জন্য আপনি কাকে দায়বদ্ধ করবেন — ডাটাবেস, ওআরএম কাঠামো (হাইবারনেট), বা অ্যাপ্লিকেশন প্রোগ্রামার?

ম্যাপিংয়ের জন্য আপনি কোন টিকা ব্যবহার করবেন (যেমন @ টেম্পোরাল)?

আপনি এই লক্ষ্য অর্জন করতে পারেন এমন অনেকগুলি উপায় রয়েছে। আপনি ডাটাবেসটিকে এটি করার অনুমতি দিতে পারেন ..

create_onকলামের জন্য আপনি একটি DEFAULTডিডিএল সীমাবদ্ধতা ব্যবহার করতে পারেন , যেমন:

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

জন্য updated_onকলাম, আপনি একটি ডিবি ট্রিগার ব্যবহার কলাম মান সেট করতে পারে CURRENT_TIMESTAMP()প্রত্যেক সময় একটি প্রদত্ত সারি রুপান্তরিত করা হয়েছে।

অথবা, সেগুলি সেট করতে জেপিএ বা হাইবারনেট ব্যবহার করুন।

ধরে নেওয়া যাক আপনার নিম্নলিখিত ডাটাবেস সারণি রয়েছে:

অডিট কলাম সহ ডাটাবেস সারণী

এবং, প্রতিটি টেবিলের মতো কলাম রয়েছে:

  • created_by
  • created_on
  • updated_by
  • updated_on

হাইবারনেট @CreationTimestampএবং @UpdateTimestampটীকাগুলি ব্যবহার করা

হাইবারনেটটি @CreationTimestampএবং @UpdateTimestampটীকাগুলি সরবরাহ করে যা ম্যাপ created_onএবং updated_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, এই নিবন্ধটি দেখুন

তবে, এমনকি যদি createdOnএবং updateOnসম্পত্তিগুলি হাইবারনেট-নির্দিষ্ট @CreationTimestampএবং @UpdateTimestampটীকাগুলি দ্বারা সেট করা থাকে , নিম্নলিখিত জেপিএ সমাধান দ্বারা চিত্রিত হিসাবে createdByএবং updatedByঅ্যাপ্লিকেশন কলব্যাকটি নিবন্ধকরণ করার প্রয়োজন হয়।

জেপিএ ব্যবহার করছে @EntityListeners

আপনি একটি এম্বেডেবলে নিরীক্ষণের বৈশিষ্ট্যগুলি encapsulate করতে পারেন:

@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, আপনি @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
}

জেপিএর সাথে নিরীক্ষণের বৈশিষ্ট্যগুলি প্রয়োগ করার বিষয়ে আরও তথ্যের জন্য @EntityListener, এই নিবন্ধটি দেখুন


খুব ভাল উত্তর, ধন্যবাদ। আমি datetimeবেশি পছন্দ করার বিষয়ে একমত নই timestamp। আপনি চান যে আপনার ডাটাবেসগুলি আপনার টাইমস্ট্যাম্পগুলির সময় অঞ্চলটি জানতে পারে। এটি সময় অঞ্চল রূপান্তর ত্রুটি প্রতিরোধ করে।
ওলে ভিভি

timestsmpটাইপ সময় অঞ্চল তথ্য সংরক্ষণ করে না। এটি কেবল অ্যাপ টিজেড থেকে ডিবি টিজেডে কথোপকথন করে। বাস্তবে, আপনি ক্লায়েন্ট টিজেড আলাদাভাবে সঞ্চয় করতে এবং ইউআই রেন্ডার করার আগে অ্যাপ্লিকেশনটিতে কথোপকথনটি করতে চান।
ভ্লাদ মিহালসিয়া

সঠিক। মাইএসকিউএল timestampসর্বদা ইউটিসিতে থাকে। মাইএসকিউএল TIMESTAMPমান সংগ্রহের জন্য বর্তমান সময় অঞ্চল থেকে ইউটিসিতে রূপান্তর করে এবং পুনরুদ্ধারের জন্য ইউটিসি থেকে বর্তমান সময় অঞ্চলে ফিরে আসে। মাইএসকিউএল ডকুমেন্টেশন: তারিখ, ডেটটাইম এবং টাইমস্ট্যাম্প প্রকারভেদ
ওলে ভিভি

17

মানগুলি সেট করতে আপনি একটি ইন্টারসেপ্টারও ব্যবহার করতে পারেন

টাইমস্ট্যাম্পড নামে একটি ইন্টারফেস তৈরি করুন যা আপনার সত্তা প্রয়োগ করে

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

এবং এটি সেশন কারখানার সাথে নিবন্ধন করুন


1
ধন্যবাদ, ধন্যবাদ অতিরিক্ত তথ্য docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/...
আন্দ্রেই Nemchenko

এটি একটি সমাধান, আপনি যদি সত্তা ম্যানেজারের পরিবর্তে সেশনফ্যাক্টরিতে কাজ করেন!
অলিভমির

কেবলমাত্র তাদের জন্য, যারা এই প্রসঙ্গে আমার মতোই একই সমস্যায় ভুগছেন: যদি আপনার সত্তা নিজেই এই অতিরিক্ত ক্ষেত্রগুলি (নির্মিতএটি, ...) সংজ্ঞায়িত না করে তবে পিতৃতুল্য শ্রেণীর কাছ থেকে উত্তরাধিকারী হয়, তবে এই প্যারেন্ট শ্রেণিটি বর্নিত করতে হবে @ ম্যাপডসুপার্ক্লাস সহ - অন্যথায় হাইবারনেট এই ক্ষেত্রগুলি খুঁজে পায় না।
অলিভমির

17

অলিভিয়ার এর সমাধান সহ আপডেট আপডেটের সময় আপনি এতে যেতে পারেন:

com.mysql.jdbc.exferences.jdbc4.MySQLIntegrityCrastraintViolationException: কলামটি 'তৈরি করা' বাতিল হতে পারে না

এটি সমাধানের জন্য, "তৈরি" বৈশিষ্ট্যের @ কলাম টিকাতে আপডেটযোগ্য = মিথ্যা যুক্ত করুন:

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

1
আমরা ব্যবহার করছি @Version। যখন কোনও সত্তা সেট করা থাকে তখন দুটি কল করা হয় একটি সংরক্ষণ করা এবং অন্যটি আপডেট করার জন্য। আমি এই কারণে একই সমস্যা ছিল। একবার আমি যুক্ত করলে @Column(updatable = false)এটি আমার সমস্যার সমাধান করে।
গণেশ সাতপুট

12

যারা সাহায্য করেছেন সবাইকে ধন্যবাদ। নিজে কিছু গবেষণা করার পরে (আমি যে লোকটি প্রশ্নটি জিজ্ঞাসা করেছি), আমি এখানে সবচেয়ে বেশি অর্থ বোধ করি:

  • ডাটাবেস কলামের ধরণ: ১৯ 1970০ সাল থেকে টাইমজোন-অজোনস্টিক সংখ্যাটি মিলিসেকেন্ডগুলির প্রতিনিধিত্ব করে decimal(20)কারণ 2 ^ 64 এর 20 ডিজিট রয়েছে এবং ডিস্কের স্থানটি সস্তা; আসুন সোজা হয়ে যাক। এছাড়াও, আমি না ব্যবহার করব DEFAULT CURRENT_TIMESTAMP, না ট্রিগারও করব। আমি ডিবিতে কোনও যাদু চাই না।

  • জাভা ক্ষেত্র প্রকার: long। ইউনিক্স টাইমস্ট্যাম্পটি বিভিন্ন longলিবগুলিতে ভালভাবে সমর্থিত, কোনও Y2038 সমস্যা নেই, টাইমস্ট্যাম্প গাণিতিকটি দ্রুত এবং সহজ (মূলত অপারেটর <এবং অপারেটর +, কোনও দিন / মাস / বছর গণনায় জড়িত না ধরে)। এবং, সর্বাগ্রে গুরুত্বপূর্ণ যে, আদিম longগুলি এবং java.lang.Longগুলি উভয়ই স্থাবর - কার্যকরীভাবে মান দ্বারা পাস করে java.util.Dates s এর বিপরীতে ; আমি foo.getLastUpdate().setTime(System.currentTimeMillis())অন্য কারও কোডটি ডিবাগ করার সময় এমন কিছু খুঁজে পেতে সত্যিই হতাশ হই ।

  • ORM ফ্রেমওয়ার্কটি স্বয়ংক্রিয়ভাবে ডেটা পূরণ করার জন্য দায়বদ্ধ হওয়া উচিত।

  • আমি এটি এখনও পরীক্ষা করে দেখিনি, তবে কেবলমাত্র ডকসটি দেখে আমি ধারণা করি যে @Temporalএটি কাজটি করবে; আমি @Versionএই উদ্দেশ্যে ব্যবহার করতে পারি কিনা সে সম্পর্কে নিশ্চিত নই । @PrePersistএবং @PreUpdateএটি ম্যানুয়ালি নিয়ন্ত্রণের জন্য ভাল বিকল্প। সমস্ত সত্তার জন্য লেয়ার সুপারটাইপ (কমন বেস ক্লাস) এ যুক্ত করা, একটি সুন্দর ধারণা প্রদান করা হয় যা আপনি সত্যই আপনার সমস্ত সত্তার জন্য টাইমস্ট্যাম্পিং চান ।


যদিও দীর্ঘায়ু এবং ল্যাংগুলি অপরিবর্তনীয় হতে পারে তবে এটি আপনার বর্ণিত পরিস্থিতিতে আপনাকে সহায়তা করবে না। তারা এখনও foo.setLastUpdate (নতুন লং (সিস্টেম.কন্ট্রেন্টটাইমমিলিস ()) বলতে পারে;
ইয়ান ম্যাকলেয়ার্ড

2
সেটা ঠিক আছে. হাইবারনেটকে যাইহোক সেটার দরকার হয় (বা এটি প্রতিচ্ছবি মাধ্যমে সরাসরি ক্ষেত্রটি অ্যাক্সেস করার চেষ্টা করবে)। আমি আমাদের অ্যাপ্লিকেশন কোড থেকে টাইমস্ট্যাম্প কে সংশোধন করছে তা তাড়া করতে অসুবিধা করার কথা বলছিলাম। যখন আপনি এটি ব্যবহারকারীর সাহায্যে এটি করতে পারেন তখন মুশকিল।
ngn

আমি আপনার দাবির সাথে একমত হয়েছি যে ওআরএম কাঠামোটি স্বয়ংক্রিয়ভাবে তারিখটি পূরণ করার জন্য দায়বদ্ধ হওয়া উচিত তবে আমি আরও এক ধাপ এগিয়ে যেতে চাই এবং ক্লায়েন্টের পরিবর্তে ডাটাবেস সার্ভারের ঘড়ি থেকে তারিখটি নির্ধারণ করা উচিত। এটি যদি এই লক্ষ্যটি অর্জন করে তবে আমি পরিষ্কার নই। স্ক্যুলে, আমি সিসডেট ফাংশনটি ব্যবহার করে এটি করতে পারি, তবে হাইবারনেট বা জেপিএ প্রয়োগের ক্ষেত্রে কীভাবে এটি করব তা আমি জানি না।
মিগুয়েলমুনোজ

আমি ডিবিতে কোনও যাদু চাই না। আপনি কী বলতে চাইছেন তা আমি দেখতে পেয়েছি তবে আমি এই বিষয়টিকে বিবেচনা করতে চাই যে ডেটাবেসটি খারাপ / নতুন / ক্লুহীন বিকাশকারীদের থেকে নিজেকে রক্ষা করা উচিত। একটি বৃহত সংস্থায় ডেটা অখণ্ডতা খুব গুরুত্বপূর্ণ, আপনি ভাল ডেটা sertোকাতে অন্যের উপর নির্ভর করতে পারবেন না। সীমাবদ্ধতা, ডিফল্ট এবং এফকে এটি অর্জনে সহায়তা করবে।
আইসগ্রাস

6

আপনি সেশন এপিআই ব্যবহার করছেন প্রিপার্সিস্ট এবং প্রি-আপডেট কলব্যাকগুলি এই উত্তর অনুসারে কাজ করবে না ।

আমি আমার কোডটিতে হাইবারনেট সেশন এর অবিরাম () পদ্ধতিটি ব্যবহার করছি যাতে আমি এই কাজটি করতে পারার একমাত্র উপায় ছিল নীচের কোড সহ এই ব্লগ পোস্টটি অনুসরণ করা ( উত্তরে পোস্ট করাও )।

@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()
শরিফ

2

আপনার সমস্ত সত্তার জন্য একটি সাধারণ বেস শ্রেণি রাখা একটি ভাল দৃষ্টিভঙ্গি। এই বেস শ্রেণিতে, আপনার আইডি সম্পত্তি থাকতে পারে যদি এটি আপনার সমস্ত সত্তা (একটি সাধারণ নকশা), আপনার তৈরি এবং শেষ আপডেটের তারিখের বৈশিষ্ট্যগুলিতে সাধারণত নামকরণ করা হয়।

তৈরির তারিখের জন্য, আপনি কেবল java.util.Date সম্পত্তি রাখুন। নিশ্চিত হন, সর্বদা নতুন তারিখ () দিয়ে এটি সূচনা করার জন্য ।

শেষ আপডেট ক্ষেত্রের জন্য, আপনি একটি টাইমস্ট্যাম্প সম্পত্তি ব্যবহার করতে পারেন, আপনাকে এটি @ ভার্সন দিয়ে মানচিত্রের প্রয়োজন। এই টীকাটি দিয়ে সম্পত্তিটি হাইবারনেট দ্বারা স্বয়ংক্রিয়ভাবে আপডেট হবে। সাবধান হন যে হাইবারনেট আশাবাদী লকিংও প্রয়োগ করবে (এটি একটি ভাল জিনিস)।


2
আশাবাদী লকিংয়ের জন্য টাইমস্ট্যাম্প কলাম ব্যবহার করা একটি খারাপ ধারণা। সর্বদা পূর্ণসংখ্যার সংস্করণ কলামটি ব্যবহার করুন। কারণ হওয়ার কারণে, 2 জেভিএম বিভিন্ন সময়ে হতে পারে এবং মিলিসেকেন্ড যথার্থতা নাও পেতে পারে। আপনি যদি পরিবর্তে হাইবারনেট ডিবি টাইমস্ট্যাম্পটি ব্যবহার করেন, তার অর্থ ডিবি থেকে অতিরিক্ত বাছাই করা। পরিবর্তে কেবল সংস্করণ নম্বর ব্যবহার করুন।
সেতু

2

কেবল শক্তিশালী করার জন্য: java.util.Calenderটাইমস্ট্যাম্পগুলির জন্য নয়java.util.Dateসময়ের এক মুহুর্তের জন্য, টাইমজোনগুলির মতো আঞ্চলিক জিনিসগুলির অজানা। বেশিরভাগ ডাটাবেসগুলি এই ফ্যাশনে জিনিসগুলি সংরক্ষণ করে (এমনকি যদি তারা তা না দেখায়; এটি সাধারণত ক্লায়েন্ট সফ্টওয়্যারটিতে টাইমজোন সেটিংস; ডেটা ভাল থাকে)


1

জাভাতে ডেটা টাইপ হিসাবে আমি java.util.Date ব্যবহার করার জন্য দৃ strongly়ভাবে সুপারিশ করি। ক্যালেন্ডার ব্যবহার করার সময় আমি বেশ খারাপ বাজে টাইমজোন সমস্যায় পড়েছিলাম। এই থ্রেড দেখুন ।

টাইমস্ট্যাম্পগুলি সেট করার জন্য আমি কোনও এওপি পদ্ধতির ব্যবহারের পরামর্শ দেব বা আপনি কেবল টেবিলে ট্রিগারগুলি ব্যবহার করতে পারেন (আসলে এটিই কেবল আমি ট্রিগারগুলির ব্যবহারকে গ্রহণযোগ্য বলে মনে করি)।


1

আপনি সময় তারিখ হিসাবে এবং ইউটিসিতে সময় সংরক্ষণ করার কথা বিবেচনা করতে পারেন। আমি সাধারণত টাইমস্ট্যাম্পের পরিবর্তে ডেটটাইম ব্যবহার করি কারণ মাইএসকিএল তারিখগুলি ইউটিসি-তে রূপান্তর করে এবং ডেটা সঞ্চয় এবং পুনরুদ্ধার করার সময় স্থানীয় সময়ে ফিরে আসে। আমি বরং এই জাতীয় যুক্তিগুলির কোনও এক জায়গায় রাখি (ব্যবসায় স্তর)। আমি নিশ্চিত যে এমন আরও কিছু পরিস্থিতি রয়েছে যেখানে টাইমস্ট্যাম্প ব্যবহার করা আরও ভাল।


1

আমাদেরও একই অবস্থা ছিল। আমরা মাইএসকিএল 5.7 ব্যবহার করছিলাম।

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

এটি আমাদের পক্ষে কাজ করেছিল।


এটি ডাটাবেসে সরাসরি কোনও এসকিউএল কোয়েরি দ্বারা ডেটা সংশোধন করা হয় এমন ক্ষেত্রেও এটি কাজ করে। @PrePersistএবং @PrePersistএই ধরনের মামলা আবরণ না।
পিডাব্রো

1

আমরা যদি @ ট্রান্সজেকশনাল ব্যবহার করি আমাদের পদ্ধতিগুলিতে ক্রিয়েশনটাইমস্ট্যাম্প এবং @ আপডেটটাইমস্ট্যাম্প ডিবিতে মানটি সংরক্ষণ করবে তবে সেভ (...) ব্যবহারের পরে বাতিল হয়ে যাবে।

এই পরিস্থিতিতে, SaveAndFlush (...) ব্যবহার করে কৌশলটি কার্যকর হয়েছিল


0

আমি মনে করি এটি জাভা কোডগুলিতে এটি খুব কম করছে না, আপনি কেবল মাইএসকিএল টেবিল সংজ্ঞাতে কলামের ডিফল্ট মান সেট করতে পারেন। এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.