Spring Data Jpa的审计功能需要引入下述依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.2</version>
</dependency>
Spring Data Jpa提供4个审计注解:@CreatedBy、@LastModifiedBy、@CreatedDate 和@LastModifiedDate
下述仅仅学习@CreatedDate和@LastModifiedDate两个注解
第一种:@LastModifiedDate
第一步:启动类中添加@EnableJpaAuditing注解表示启用JPA审计
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@EnableJpaAuditing
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
第二步: 数据库中创建表tb_user
CREATE TABLE `tb_user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(32) NOT NULL COMMENT '姓名',
`age` int NOT NULL COMMENT '年龄',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) COMMENT='用户表';
第三步: 在实体中添加注解 @EntityListeners(AuditingEntityListener.class) 监听实体变化,并且在updateTime字段上增加 @LastModifiedDate注解
import lombok.Data;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.Date;
@EntityListeners(AuditingEntityListener.class)
@Data
@Entity
@Table(name = "tb_user")
public class TbUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "age")
private Integer age;
@Column(name = "create_time")
private Date createTime;
@LastModifiedDate
@Column(name = "update_time")
private Date updateTime;
}
第四步:往表tb_user中插入一行记录
INSERT INTO `tb_user` (`id`, `name`, `age`, `create_time`, `update_time`) VALUES('1','张三','18','2021-11-09 00:00:00',NULL);

第五步:构建测试代码去测试@LastModifiedDate注解
import com.bc.single.dao.UserDao;
import com.bc.single.entity.TbUser;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
class ApplicationTests {
@Autowired
private UserDao userDao;
@Test
void contextLoads(){
TbUser user=userDao.findAll().get(0);
user.setName("李四");
userDao.save(user);
}
}
执行上述测试后,就会发现数据库中该条数据的update_time字段值已经自动产生了

特别提示:如果是使用JPA的save(实体)方法去更新数据,@LastModifiedDate注解使用是没有问题的。如果是使用SQL/JPQL语句去更新数据,@LastModifiedDate注解的使用就会失效,例如我们在UserDao中构建一个JPQL更新操作语句updateTest:
import com.bc.single.entity.TbUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
public interface UserDao extends JpaRepository<TbUser,Integer> {
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query("update TbUser set name ='王五' where id=:id")
void updateTest(@Param("id") Integer id);
}
测试类中的测试方法如下:
import com.bc.single.dao.UserDao;
import com.bc.single.entity.TbUser;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
class ApplicationTests {
@Autowired
private UserDao userDao;
@Test
void contextLoads(){
userDao.updateTest(1);
}
}
执行上述结果后,其结果为:

可以看到使用上述JPQL更新操作语句时,@LastModifiedDate注解已经失效了。针对这种情况,最简单的解决办法,就是在JPQL更新操作语句里对updateTime字段赋值current_time即可。
import com.bc.single.entity.TbUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
public interface UserDao extends JpaRepository<TbUser,Integer> {
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query("update TbUser set name ='王五',updateTime=current_time where id=:id")
void update(@Param("id") Integer id);
}
第二种:@CreatedDate
在上述实体类的基础之上,在实体类的createTime字段上增加 @CreatedDate注解
import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.Date;
@EntityListeners(AuditingEntityListener.class)
@Data
@Entity
@Table(name = "tb_user")
public class TbUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "age")
private Integer age;
@CreatedDate
@Column(name = "create_time")
private Date createTime;
@LastModifiedDate
@Column(name = "update_time")
private Date updateTime;
}
在测试类中创建新对象进行保存:
import com.bc.single.dao.UserDao;
import com.bc.single.entity.TbUser;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
class ApplicationTests {
@Autowired
private UserDao userDao;
@Test
void contextLoads(){
TbUser user=new TbUser();
user.setName("赵六");
user.setAge(18);
userDao.save(user);
}
}
数据库中的数据记录如下:

可以看到在新增一条记录的时候,create_time和update_time字段都会自动赋值
本文介绍了Spring Data Jpa的审计功能,重点讲解了@LastModifiedDate和@CreatedDate两个注解的使用。通过启用JPA审计,实体监听器和数据库表的设计,展示了如何在保存和更新操作中自动维护创建和修改时间。然而,当使用JPQL更新数据时,@LastModifiedDate注解可能失效,解决方案是在更新语句中显式设置当前时间。
543

被折叠的 条评论
为什么被折叠?



