当前位置:网站首页>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 .
边栏推荐
- 网上开期货账户安全吗?手续费怎么申请才低?
- Cet
- OSPF综合实验
- Several implementations of PHP to solve concurrency problems
- Go language context control function execution timeout return
- MySQL数据库常用命令
- WPF 实现用户头像选择器
- 基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用
- Food safety | eight questions and eight answers take you to know crayfish again! This is the right way to eat!
- What is an IP SSL certificate and how to apply for it?
猜你喜欢

PageHelper还能结合Lambda表达式实现简洁的分页封装

OSPF---开放式最短优先路径协议

SLA 、SLO & SLI

计算日期或日期格式化

OSPF comprehensive experiment

Tme2022 campus recruitment background development / operation development / business operation and maintenance / application development written examination (I) a little self analysis of programming q

十九岁的总结

IDEA集成SVN代码管理常用功能

Tkinter module advanced operations (I) -- transparent buttons, transparent text boxes, custom buttons and custom text boxes

What is an IP SSL certificate and how to apply for it?
随机推荐
Trooper
go接口变量的类型断言
Highlights
Lwip之内存与包缓冲管理
精彩记录
论文阅读_多任务学习_MMoE
Redis source code and design analysis -- 18. Analysis of redis network connection Library
MySQL数据库常用命令
Redistemplate solves the problem of oversold inventory in the seckill system with high speed - redis transaction + optimistic lock mechanism
How to fix the first row title when scrolling down in Excel table / WPS table?
C LINQ de Duplication & de duplication sum
如何选择数字孪生可视化平台
Summary of knowledge points for final review of server-side architecture design
Mock service Moco series (I) - introduction, first demo, get request, post request
SLA 、SLO & SLI
Auditing相关注解
Nineteen year old summary
Mock service Moco series (III) - redirection, regular expression, delay, template, event, sub module design
What is an IP SSL certificate and how to apply for it?
为什么数字化未来取决于3D实时渲染