springDataJpa入門教程
-
springDataJpa入門教程(1)-基於springBoot的基本增刪改查
-
springDataJpa入門教程(2)-Specification動態條件查詢+排序+分頁
-
springDataJpa入門教程(3-1)-基於EntityManager原生sql多表聯合查詢+動態條件查詢+分頁
-
springDataJpa入門教程(3-2)-基於EntityManager原生sql多表聯合查詢+動態條件查詢+分頁返回自定義實體類對象
-
springDataJpa入門教程(4)-Example單表動態條件查詢+分頁
-
springDataJpa入門教程(5)-單表動態條件查詢+分頁
-
springDataJpa入門教程(6)-多表動態條件查詢+分頁
-
springDataJpa入門教程(7)-基於springDataJpa投影(Projection)返回自定義實體類對象
-
springDataJpa入門教程(8)-JPA EnableJpaAuditing 審計功能
-
springDataJpa入門教程(9)-spring jpa實體屬性類型轉換器AttributeConverter的用法
-
springDataJpa入門教程(10)-JPA使用過程中遇到的坑及解決方法
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方法被調用的時候,時間字段會自動設置並插入數據庫,但是CreatedBy和LastModifiedBy並沒有賦值,因爲需要實現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,歡迎大家一起交流學習。