首页 > 编程知识 正文

springboot整合jpa分页查询,springboot中使用jpa实现分组查询

时间:2023-05-06 15:45:22 阅读:272992 作者:4938

SpringDataJPA中有个注解@Audited

只需在Entity中加上注解@Audited,就会自动帮你记录下Entity对应的表的所有操作记录insert,update,delete,会在数据库帮你生成一张表xxx_AUD;

这是在SpringDataJPA框架才能使用的一个注解,如果使用mybatis怎么办呢?

废话不多说,下面直接上代码:

需要添加的依赖主要有下面这些:

compile('org.springframework.boot:spring-boot-starter-web') compile('com.baomidou:mybatis-plus-boot-starter:2.2.0') compile('org.apache.logging.log4j:log4j-1.2-api') compile('org.springframework.boot:spring-boot-starter-aop') compile('com.alibaba:druid:1.1.6') compile('org.projectlombok:lombok:1.16.10') compile('com.alibaba:fastjson:1.2.47') compile('org.springframework.boot:spring-boot-starter-undertow') compile('mysql:mysql-connector-java:5.1.21')

 数据库用的sql server,然后新建一张表来记录其他表的操作日志: 

@Data@Builder@AllArgsConstructor@NoArgsConstructor@Accessors(chain = true)@TableName("SqlOperateLog")public class SqlOperationLog implements Serializable { private static final long serialVersionUID = 1L; @TableField("ID") private Long id; @TableField("Type") private String type; @TableField("AfterValue") private String afterValue; @TableField("BeforeValue") private String beforeValue; @TableField("CreateTime") private Date createTime; @TableField("TableName") private String tableName; @TableField("UserID") private Integer userId;}

与之对应的mapper:

@Repository@Mapperpublic interface SqlOperationLogMapper extends BaseMapper<SqlOperationLog> {}

注意: SqlOperationLog 和他的mapper不要放mapper包下了,下面aop会扫描这个包;

新建一个类实现ApplicationContextAware,方便从spring容器中获取bean

@Componentpublic class RecordBeanFactory implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (this.applicationContext == null) { this.applicationContext = applicationContext; } } public static Object getBean(Class<?> clazz) { if (applicationContext == null) { return null; } return applicationContext.getBean(clazz); }}

拦截器记录操作用户信息:

public class MyInterceptor implements HandlerInterceptor { public static final ThreadLocal<UserInfo> USER_INFO = new ThreadLocal<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 从security的context中获取登陆用户信息 UserVO vo = (UserVO) SecurityContextHolder .getContext() .getAuthentication() .getPrincipal(); UserInfo userInfo = UserInfo.builder() .userId(vo.getUserId()) .userName(vo.getNickName()) .userIp(request.getRemoteAddr()) .build(); USER_INFO.set(userInfo); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { USER_INFO.remove(); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }}

因为这里用了Spring security框架,可以直接从SecurityContextHolder上下文中获取登陆用户的信息;如果你用了别的框架,换别的实现也是一样的;这里不再细说

最后就是最重要的aop的代码:

@Aspect@Componentpublic class SqlAspect { private SqlOperationLog sqlOperationLog; @Autowired private SqlOperationLogMapper sqlOperationLogMapper; /** * mybatis-plus表操作都返回的是integer,表达式根究自己项目包结构来写,这里不展示我的包结构了 */ @Pointcut("execution(Integer com.demo.demo.mapper.*.*(..))") private void mapper() { } /** * 记录表的操作日志,insert,update,delete(逻辑删除) * * @param joinPoint */ @Around("mapper()") public Object recordOperate(ProceedingJoinPoint joinPoint) throws Exception { // 获取被代理对象 Object target = joinPoint.getTarget(); MapperProxy invo = (MapperProxy) Proxy.getInvocationHandler(target); Class<? extends MapperProxy> mapperProxy = invo.getClass(); Field mapperInterface1 = mapperProxy.getDeclaredField("mapperInterface"); mapperInterface1.setAccessible(true); Class proxyClass = (Class) mapperInterface1.get(invo); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); // 被代理方法的参数 Object[] args = joinPoint.getArgs(); sqlOperationLog = new SqlOperationLog(); sqlOperationLog.setType(method.getName()); sqlOperationLog.setUserId(MyInterceptorConfig.USER_INFO.get().getUserId()); String beforeValue = beforeOperate(args, proxyClass); sqlOperationLog.setBeforeValue(beforeValue); // 执行sql Integer result = 0; try { result = (Integer) joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } // 执行成功 if (result > 0) { String afterValue = afterOperate(args); sqlOperationLog.setAfterValue(afterValue); } sqlOperationLogMapper.insert(sqlOperationLog); return result; } /** * 操作前的值 * * @param args 参数 * @param proxyClass 被代理类 * @return 修改器的值, json格式 * @throws Exception */ private String beforeOperate(Object[] args, Class proxyClass) throws Exception { for (Object arg : args) { Class<?> clazz = arg.getClass(); String entityName = clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1); Object bean = RecordBeanFactory.getBean(proxyClass); // 获取mapper的selectById方法 Method selectById = proxyClass.getMethod("selectById", Serializable.class); Method[] methods = clazz.getDeclaredMethods(); Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { // 每个entity对应表的主键ID都有@TableId注解 if (declaredField.getAnnotation(TableId.class) != null) { System.out.println("主键:" + declaredField.getName()); // 获取主键的值,因为每个表的主键名字不一定都是id String primaryKeyMethod = "get" + declaredField.getName(); for (Method method : methods) { if (primaryKeyMethod.equalsIgnoreCase(method.getName())) { // 调用getId方法 Object id = method.invoke(arg); // 调用对应mapper的selectById Object invoke = selectById.invoke(bean, id); System.out.println("修改前==" + JSON.toJSONString(invoke)); return JSON.toJSONString(invoke); } } } } } return null; } /** * 数据库操作后 * * @param args 修改的对象 * @return 修改后的对象json字符串 */ public String afterOperate(Object[] args) throws Exception { if (args == null) { return null; } // 遍历参数对象 for (Object arg : args) { // 获取对象类型 Class<?> clazz = arg.getClass(); TableName annotation = clazz.getAnnotation(TableName.class); if (annotation == null) { return null; } String tableName = annotation.value(); sqlOperationLog.setTableName(tableName); sqlOperationLog.setCreateTime(new Date()); return JSON.toJSONString(arg); } return null; }}

以上就是全部的相关代码,如有问题,欢迎交流

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。