傻傻分不清楚的 @CreationTimestamp、@UpdateTimestamp、@CreatedDate、@LastModifiedDate、@CreatedBy、@LastModifiedBy;相信在对于我们想要实现JPA自动更新赋值实体类的创建时间和更新时间的场景中,对于这些注解大家并不陌生;但是在使用的时候却不止从何入手,今天我门就来聊一聊这些注解的正确使用方法

操作数据库映射实体类时,通常需要记录createTime和updateTime,如果每个对象新增或修改去都去手工操作创建时间、更新时间,会显得比较繁琐。

1. @CreationTimestamp、@UpdateTimestamp

Hibernate 提供了类似上述时间注解的功能实现,这种方法只需要在实体类上配置

@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
     /**
     * 自增主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Integer id;

     /**
     * 更新时间
     */
    @CreationTimestamp
    @Column(updatable = false, nullable = false)

    private Long createTime;

     /**
     * 创建时间
     */
    @UpdateTimestamp
    @Column(nullable = false)
    private Long updateTime;
}

注意:使用@UpdateTimestamp@CreationTimestam的属性类型只能为Date、LocalDateTime,不能为Long,意味着不能直接生成时间戳。

2. @CreatedDate、@LastModifiedDate

Springboot JPA 也提供了自动填充这两个字段的功能,简单配置一下即可。@CreatedDate、@LastModifiedDate 使用@CreatedDate@LastModifiedDate的属性类型可以为Date、Long、Timestamp、LocalDateTime ,意味着不能直接生成时间戳。

首先,我们的很多实体类都是需要创建时间和更新时间的,我们不想在每个实体类里都去定义这两个字段,那么我们把它抽取到基类中,让实体类去继承它。

package com.tianyalei.testautotime.entity;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;

/**
 * Created by wuwf on 17/4/21.
 */
@Data
@MappedSuperclass
// 不加此注解的话@CreatedDate,@LastModifiedDate不起作用, 表示监听这个类 AuditingEntityListener.class是自带的默认监听类
@EntityListeners(AuditingEntityListener.class)
// @DynamicInsert,@DynamicUpdate只插入更新已更改字段
@DynamicInsert
@DynamicUpdate
public abstract class BaseEntity {
     /**
     * 自增主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Integer id;

     /**
     * 更新时间
     */
    @CreatedDate
    @Column(updatable = false, nullable = false)

    private Long createTime;

     /**
     * 创建时间
     */
    @LastModifiedDate
    @Column(nullable = false)
    private Long updateTime;
}

然后,在Application启动类中添加注解 @EnableJpaAuditing

@EnableJpaAuditing
@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
    
}

3. @CreatedBy、@LastModifiedBy

此外,Spring Data JPA 还提供 @CreatedBy 和 @LastModifiedBy 注解,用于保存和更新当前操作用户的信息(如id、name)。如果有这方面的需求,可以参考下面的配置实现:

package com.tianyalei.testautotime.entity;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;

/**
 * Created by wuwf on 17/4/21.
 */
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
     /**
     * 自增主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Integer id;

     /**
     * 更新时间
     */
    @CreatedDate
    @Column(updatable = false, nullable = false)

    private Long createTime;

     /**
     * 创建时间
     */
    @LastModifiedDate
    @Column(nullable = false)
    private Long updateTime;

     /**
     * 创建人
     */
    @CreatedBy
    private Integer createBy;

    /**
     * 最后修改人
     */
    @LastModifiedBy
    private Integer lastModifiedBy;
}

需要实现org.springframework.data.domain.AuditorAware这个类,根据你需要返回的类型修改这个T,比如我需要返回的是数值,就是Integer。需要注意的是,类需要加上@Component以便spring扫描到,否则不起作用。

配置实现AuditorAware接口,以获取字段需要插入的信息:

@Component
@Slf4j
public class SpringSecurityAuditorAware implements AuditorAware<Integer> {

    /**
     * 返回操作员标志信息
     *
     * @return
     */
    @Override
    public Optional<Integer> getCurrentAuditor() {
        // 这里应根据实际业务情况获取具体信息
        return Optional.of(new Random().nextInt(1000));
    }

}

如果有多个实现,则会报错找到两个实现类

No qualifying bean of type ‘org.springframework.data.domain.AuditorAware<?>’ available: expected single matching bean but found 2: springSecurityAuditorAware,springSecurityAuditorAwareTest

这时,只需要在EnableJpaAuditing注解后增加参数说明需要使用哪个就可以

@SpringBootApplication
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}