springDataJpa入門教程(8)-JPA EnableJpaAuditing 審計功能

springDataJpa入門教程

springDataJpa入門教程(8)-JPA EnableJpaAuditing 審計功能

在實際的業務系統中,往往需要記錄表數據的創建時間、創建人、修改時間、修改人。每次手動記錄這些信息比較繁瑣,springDataJpa的審計功能可以幫助我們來做這些繁瑣的配置,下面來講一講springDataJpa的審計功能怎麼使用。有需要源碼的朋友,請到git上下載源碼,源碼地址:源碼下載地址。java學習交流羣:184998348,歡迎大家一起交流學習。

JPA Audit 說明

在spring jpa中,支持在字段或者方法上進行註解@CreatedDate@CreatedBy
@LastModifiedDate@LastModifiedBy,從字面意思可以很清楚的瞭解,這幾個註解的用處。

@CreatedDate
表示該字段爲創建時間時間字段,在這個實體被insert的時候,會設置值

@CreatedBy
表示該字段爲創建人,在這個實體被insert的時候,會設置值

@LastModifiedDate@LastModifiedBy同理。

如何使用審計功能

首先申明實體類,需要在類上加上註解@EntityListeners(AuditingEntityListener.class),其次在application啓動類中加上註解EnableJpaAuditing,同時在需要的字段上加上@CreatedDate@CreatedBy@LastModifiedDate@LastModifiedBy等註解。

這個時候,在jpa的save方法被調用的時候,時間字段會自動設置並插入數據庫,但是CreatedByLastModifiedBy並沒有賦值,因爲需要實現AuditorAware接口來返回你需要插入的值。

1.編寫AuditorAware

package com.thizgroup.jpa.study.config;

import java.util.Optional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;

@Configuration//使用jpa審計功能,保存數據時自動插入創建人id和更新人id
public class UserAuditorAware implements AuditorAware<Long> {

  @Override
  public Optional<Long> getCurrentAuditor() {
    //從session中獲取當前登錄用戶的id
    Long userId = 2L;
    return Optional.of(userId);
  }
}

2.在實體類中聲明@EntityListeners和相應的註解
考慮到所有實體都需要聲明,就寫在BaseEntity中,其他的實體類通過繼承BaseEntity來實現審計功能。

package com.thizgroup.jpa.study.model;


import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import lombok.Data;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@MappedSuperclass//這個註解的意思是這個類jpa不會爲它創建數據庫表,
//jpa會將這個類的所有字段映射到它的子類的數據庫表中
@Data
@EntityListeners(AuditingEntityListener.class)//對實體屬性變化的跟蹤,它提供了保存前,保存後,更新前,
// 更新後,刪除前,刪除後等狀態,就像是攔截器一樣,你可以在攔截方法裏重寫你的個性化邏輯。
public abstract class BaseEntity   implements Serializable {

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

  @CreatedDate//自動填充創建時間
  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "create_date",columnDefinition = "timestamp")
  protected Date createDate;//創建時間

  @LastModifiedDate//自動填充修改時間
  @Temporal(TemporalType.TIMESTAMP)
  @Column(name = "modify_date",columnDefinition = "timestamp")
  protected Date modifyDate;//修改時間

  @CreatedBy//自動填充創建人
  @Column(name = "created_by",columnDefinition = "bigint")
  protected Long createdBy;//創建人

  @LastModifiedBy//自動填充修改人
  @Column(name = "last_modify_by",columnDefinition = "bigint")
  protected Long lastModifyBy;//修改人

}

然後在子類中繼承BaseEntity,下面以User類爲例,

package com.thizgroup.jpa.study.model;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "tb_user")
@Data//使用lombok生成getter、setter
@NoArgsConstructor//生成無參構造方法
public class User extends BaseEntity{

  @Column(name = "name",columnDefinition = "varchar(64)")
  private String name;

  @Column(name = "mobile",columnDefinition = "varchar(64)")
  private String mobile;

  @Column(name = "email",columnDefinition = "varchar(64)")
  private String email;

  @Column(name = "age",columnDefinition = "smallint(64)")
  private Integer age;

  @Column(name = "birthday",columnDefinition = "timestamp")
  private Date birthday;

  //地址
  @Column(name = "address_id",columnDefinition = "bigint(20)")
  private Long addressId;

  @Builder(toBuilder = true)
  public User(Long id,String name, String mobile, String email, Integer age, Date birthday,
      Long addressId) {
    this.id = id;
    this.name = name;
    this.mobile = mobile;
    this.email = email;
    this.age = age;
    this.birthday = birthday;
    this.addressId = addressId;
  }
}

3.在Application 中啓用審計@EnableJpaAuditing

package com.thizgroup.jpa.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
//配置springDataJpa掃描Repository的包路徑
@EntityScan(basePackages = {"com.thizgroup.jpa.study.model","com.thizgroup.jpa.study.dto"})
@EnableJpaRepositories("com.thizgroup.jpa.study.dao")
@EnableJpaAuditing//啓動jpa審計功能
public class JpaApplication {

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

}

注意:經過測試如果你的實體類上面的多個字段使用了@CreatedBy這樣的註解,只會有一個生效,也就是說在一次請求中,只會被調用一次。

接下來,寫個例子來測試一下,在UserService接口添加一個保存用戶的方法,

package com.thizgroup.jpa.study.service;

import com.thizgroup.jpa.study.model.User;
import java.util.List;

/**
 * 用戶服務
 */
public interface IUserService {
	  /**
   * 添加用戶
   * @param user
   * @return
   */
  User addUser(User user);
}

然後在UserServiceImpl實現類實現該方法,

 @Override
  public User addUser(User user) {
    User savedUser = userRepository.save(user);
    return savedUser;
  }

寫個單元測試來驗證下jpa審計是否生效,

package com.thizgroup.jpa.study.service;

import com.thizgroup.jpa.study.JpaApplication;
import com.thizgroup.jpa.study.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@SpringBootTest(classes={JpaApplication.class})
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public class UserServiceImplTest {

  @Autowired
  private IUserService userService;

   @Test
  @Rollback(value = false)
  public void addUserTest(){
    User user = User.builder()
        .name("李元芳")
        .email("[email protected]")
        .birthday(DateUtils.parse("1998-09-08 12:14:15", "yyyy-MM-dd HH:mm:ss"))
        .age(30)
        .mobile("18755634343")
        .build();
    userService.addUser(user);
  }
}

運行一下單元測試,結果如下:
在這裏插入圖片描述
好了,至此,springDataJpa功能就介紹完了,有需要源碼的朋友,請到git上下載源碼,源碼地址:https://github.com/hgq0916/springdatajpa-study.git。java學習交流羣:184998348,歡迎大家一起交流學習。

上一篇:springDataJpa入門教程(7)-基於springDataJpa投影(Projection)返回自定義實體類對象
下一篇:springDataJpa入門教程(9)-spring jpa實體屬性類型轉換器AttributeConverter的用法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章