当前位置:网站首页>Auditing related notes
Auditing related notes
2022-07-25 17:55:00 【InfoQ】
Auditing What does it mean ?
- @CreatedBy Which user created it .
- @CreatedDate When it was created .
- @LastModifiedBy Finally, the user who modifies the entity .
- @LastModifiedDate Time of last modification .
Auditing How to achieve ?
The first way : Directly add the above four annotations to the example
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "addresses")
@EntityListeners(AuditingEntityListener.class)
public class User implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String name;
private String email;
@Enumerated(EnumType.STRING)
private SexEnum sex;
private Integer age;
@OneToMany(mappedBy = "user")
@JsonIgnore
private List<UserAddress> addresses;
private Boolean deleted;
@CreatedBy
private Integer createUserId;
@CreatedDate
private Date createTime;
@LastModifiedBy
private Integer lastModifiedUserId;
@LastModifiedDate
private Date lastModifiedTime;
}
@CreatedBy
private Integer createUserId;
@CreatedDate
private Date createTime;
@LastModifiedBy
private Integer lastModifiedUserId;
@LastModifiedDate
private Date lastModifiedTime;
@EntityListeners(AuditingEntityListener.class)
public class MyAuditorAware implements AuditorAware<Integer> {
// Need to achieve AuditorAware Interface , Return to the current user ID
@Override
public Optional<Integer> getCurrentAuditor() {
ServletRequestAttributes servletRequestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
Integer userId = (Integer) servletRequestAttributes.getRequest().getSession().getAttribute("userId");
return Optional.ofNullable(userId);
}
}
public interface AuditorAware<T> {
T getCurrentAuditor();
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
Integer userId = ((LoginUserInfo) authentication.getPrincipal()).getUser().getId();
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(JpaAuditingRegistrar.class)
public @interface EnableJpaAuditing {
//auditor User acquisition method , The default is to find AuditorAware Implementation class of ;
String auditorAwareRef() default "";
// Whether to set the time when creating and modifying , The default is true
boolean setDates() default true;
// Whether it is also used as modification when creating , The default is true
boolean modifyOnCreate() default true;
// How to generate time , The default is to take the current time ( Why provide this function ? Because you may want to keep the same time during the test , It provides a custom method );
String dateTimeProviderRef() default "";
}
@Configuration
@EnableJpaAuditing
public class JpaConfiguration {
@Bean
@ConditionalOnMissingBean(name = "myAuditorAware")
MyAuditorAware myAuditorAware() {
return new MyAuditorAware();
}
}
- Here's a Congifuration Best practice writing . Why should we write a separate JpaConfiguration Configuration file for , Rather than taking @EnableJpaAuditing Put it in JpaApplication In the class of ? Because in that case JpaConfiguration Files can be loaded separately 、 Individual test , If it's all in Appplication Words in class , Don't you have to start the whole application every time you test ?
- MyAuditorAware It can also be done through @Component Load annotation , Why do I recommend @Bean What is the way? ? Because this way, users can know which components we have customized directly through our configuration file , Will not let the user have unnecessary surprise , This is a bit of writing framework Experience , For your reference .
@DataJpaTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Import(JpaConfiguration.class)
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@MockBean
MyAuditorAware myAuditorAware;
@Test
public void testAuditing() {
// Because test case simulation web context Environment is not our focus , We use @MockBean,mock Lose our way , Looking forward to returning 13 This user ID
Mockito.when(myAuditorAware.getCurrentAuditor()).thenReturn(Optional.of(13));
// We don't explicitly specify the update time 、 Creation time 、 Updated by 、 founder
User user = User.builder()
.name("jack")
.email("[email protected]")
.sex(SexEnum.BOY)
.age(20)
.build();
userRepository.save(user);
// Verify whether there is a creation time 、 Update time ,UserID Whether it is right ;
List<User> users = userRepository.findAll();
Assertions.assertEquals(13,users.get(0).getCreateUserId());
Assertions.assertNotNull(users.get(0).getLastModifiedTime());
System.out.println(users.get(0));
}
}
- We make use of @MockBean simulation MyAuditorAware Return results 13 This UserID;
- We test and verify create_user_id Is it what we expect .
User(id=1, name=jack, [email protected], sex=BOY, age=20, deleted=null, createUserId=13, createTime=Sat Oct 03 21:19:57 CST 2020, lastModifiedUserId=13, lastModifiedTime=Sat Oct 03 21:19:57 CST 2020)
The second way : The entity implements Auditable Interface
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "addresses")
@EntityListeners(AuditingEntityListener.class)
public class User implements Auditable<Integer,Long, Instant> {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String name;
private String email;
@Enumerated(EnumType.STRING)
private SexEnum sex;
private Integer age;
@OneToMany(mappedBy = "user")
@JsonIgnore
private List<UserAddress> addresses;
private Boolean deleted;
private Integer createUserId;
private Instant createTime;
private Integer lastModifiedUserId;
private Instant lastModifiedTime;
@Override
public Optional<Integer> getCreatedBy() {
return Optional.ofNullable(this.createUserId);
}
@Override
public void setCreatedBy(Integer createdBy) {
this.createUserId = createdBy;
}
@Override
public Optional<Instant> getCreatedDate() {
return Optional.ofNullable(this.createTime);
}
@Override
public void setCreatedDate(Instant creationDate) {
this.createTime = creationDate;
}
@Override
public Optional<Integer> getLastModifiedBy() {
return Optional.ofNullable(this.lastModifiedUserId);
}
@Override
public void setLastModifiedBy(Integer lastModifiedBy) {
this.lastModifiedUserId = lastModifiedBy;
}
@Override
public void setLastModifiedDate(Instant lastModifiedDate) {
this.lastModifiedTime = lastModifiedDate;
}
@Override
public Optional<Instant> getLastModifiedDate() {
return Optional.ofNullable(this.lastModifiedTime);
}
@Override
public boolean isNew() {
return id==null;
}
}
The third way : utilize @MappedSuperclass annotation

package com.example.jpa.example1.base;
import org.springframework.data.annotation.*;
import javax.persistence.MappedSuperclass;
import java.time.Instant;
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@CreatedBy
private Integer createUserId;
@CreatedDate
private Instant createTime;
@LastModifiedBy
private Integer lastModifiedUserId;
@LastModifiedDate
private Instant lastModifiedTime;
}
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "addresses")
public class User extends BaseEntity {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String name;
private String email;
@Enumerated(EnumType.STRING)
private SexEnum sex;
private Integer age;
@OneToMany(mappedBy = "user")
@JsonIgnore
private List<UserAddress> addresses;
private Boolean deleted;
}
- Removed @EntityListeners(AuditingEntityListener.class);
- Removed @CreatedBy、@CreatedDate、@LastModifiedBy、@LastModifiedDate Public fields of four annotations .
边栏推荐
- Which one of the electronic products has a longer service life??
- mysql case when
- UFT(QTP)-总结点与自动化测试框架
- 【硬件工程师】DC-DC隔离式开关电源模块为什么会用到变压器?
- PHP解决并发问题的几种实现
- [cadence Allegro PCB design] permanently modify the shortcut key (customized) ~ it is valid for personal test~
- 越来越成熟的Rust,都应用了哪些场景呢?
- Redis源码与设计剖析 -- 15.RDB持久化机制
- 计算日期或日期格式化
- 一篇文章了解超声波加湿器
猜你喜欢

我也是醉了,Eureka 延迟注册还有这个坑!

An article about ultrasonic humidifier

11. Camera and lens

Idea 必备插件

Food safety | eight questions and eight answers take you to know crayfish again! This is the right way to eat!

Hcip first day experiment

Automated test Po design model

喜讯!瑞云科技被授予“海上扬帆”5G融合应用专委会成员单位

SVN客户端(TortoiseSVN)安装及使用说明

Cet
随机推荐
Hit the test site directly: summary of common agile knowledge points in PMP examination
3DCAT v2.1.3新版本发布,这三大功能更新你不容错过!
Redis source code and design analysis -- 17. Redis event processing
Principle and implementation of UDP penetration NAT in P2P
Cross validation (CV) learning notes
UFT (QTP) - summary points and automated test framework
Basic knowledge of software testing (mind mapping)
Unity 贝塞尔曲线的创建
How many points did NPDP pass? How to pass with high scores?
交叉验证(cv)学习笔记
我也是醉了,Eureka 延迟注册还有这个坑!
我也是醉了,Eureka 延迟注册还有这个坑!
What is an IP SSL certificate and how to apply for it?
How to read a Book
简述聚簇索引、二级索引、索引下推
Cet
Pymongo saves data in dataframe format (insert_one, insert_many, multi-threaded saving)
直击考点:PMP考试中常见敏捷知识点汇总
精彩记录
[solution] the Microsoft edge browser has the problem of "unable to access this page"