day41-javaWeb

目录

  • Spring事务管理
    • 案例:删除部门
      • 需求:
    • 分析:
      • 步骤:
      • 代码实现
        • Service层
          • DeptServiceImpl
          • DeptLogService
          • DeptLogServiceImpl
        • Mapper层
          • DeptMapper
          • EmpMapper
          • DeptLogMapper
        • 数据库表
          • dept_log 日志表
        • 实体类
          • DeptLog
  • AOP
    • 概述
    • 入门案例
      • 需求
      • 步骤
      • 代码实现
        • TimeAspect
    • AOP通知
    • AOP通知顺序
    • AOP连接点
    • AOP切入点表达式
      • 切入点表达式execution
      • 切入点表达式@annotation
      • 自定义注解
      • DeptServiceImpl
    • AOP案例
      • 需求
      • 代码实现
        • 数据库表
        • 切面类OperateAspect
        • OperateLogMapper
        • OperateLog操作日志实体类
        • 自定义注解
        • DeptServiceImpl

Spring事务管理

案例:删除部门

需求:

当部门解散了不仅需要把部门信息删除了,还需要把该部门下的员工数据也删除了。

记录解散部门的日志到日志表

分析:

考虑到删除过程中可能会出现异常,使用Spring框架的事务管理功能实现解散部门功能

无论解散部门是否成功都应该记录日志,故记录日志应开启新事务

步骤:

1.根据id删除部门

2.根据dept_id删除员工

3.为解散部门方法添加事务

4.记录解散部门日志到日志表

代码实现

Service层

DeptServiceImpl
package com.itheima.service.impl;

import com.itheima.anno.MyLog;
import com.itheima.mapper.DeptMapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Dept;
import com.itheima.pojo.DeptLog;
import com.itheima.service.DeptLogService;
import com.itheima.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
//@Transactional//添加在类上表示为该类的所有方法添加事务,
// 添加在接口上表示为该接口的所有实现类的所有方法添加事务
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private DeptLogService deptLogService;

    @Override
    //在Spring的事务管理中,默认只有运行时异常 RuntimeException才会回滚。
    @Transactional(rollbackFor = Exception.class)//为该方法开启事务,指定任何异常都回滚事务
    public void deleteById(Integer id) throws Exception {
        try {
            //调用mapper层的deleteById方法
            deptMapper.deleteById(id);

//        int i = 1/0;//模拟出现异常
            //模拟非运行时异常抛出,若不使用rollbackFor属性指定则事务不会因为此异常回滚
/*        if (true){
            throw new Exception("出错了");
        }*/
            //删除该部门员工
            empMapper.deleteByDeptId(id);
        } finally {
            //无论是否成功都要记录部门日志
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,此次解散的是:"+id+"号部门");
            //开启了新的事务
            deptLogService.insert(deptLog);
        }
    }
}
DeptLogService
package com.itheima.service;

import com.itheima.pojo.DeptLog;

public interface DeptLogService {
    /**
     * 添加部门操作日志
     * @param deptLog
     */
    void insert(DeptLog deptLog);
}
DeptLogServiceImpl
package com.itheima.service.impl;

import com.itheima.mapper.DeptLogMapper;
import com.itheima.pojo.DeptLog;
import com.itheima.service.DeptLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 部门日志记录
 * propagation属性默认为REQUIRED:即需要事务,有则加入,无则创建新的事务
 * REQUIRES_NEW:需要新的事务,无论有无,总是创建事务
 * 当本方法被其他事务方法调用时,挂起其他事务,为本方法创建新的事务并执行完毕后,再执行其他事务
 */
@Service
public class DeptLogServiceImpl implements DeptLogService {

    @Autowired
    private DeptLogMapper deptLogMapper;

    @Override
    //配置propagation属性,设置为当前方法开启新的事务,避免加入其它事务中一起回滚
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void insert(DeptLog deptLog) {
        deptLogMapper.insert(deptLog);
    }
}

Mapper层

DeptMapper
@Mapper
public interface DeptMapper {
    /**
     * 根据id删除部门信息
     * @param id   部门id
     */
    @Delete("delete from dept where id = #{id}")
    void deleteById(Integer id);
}
EmpMapper
@Mapper
public interface EmpMapper {

    //根据部门id删除部门下所有员工
    @Delete("delete from emp where dept_id=#{deptId}")
    public int deleteByDeptId(Integer deptId);
    
}
DeptLogMapper
package com.itheima.mapper;

import com.itheima.pojo.DeptLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DeptLogMapper {
    /**
     * 添加解散部门日志
     * @param deptLog
     */
    @Insert("insert into dept_log(create_time, description) values (#{createTime},#{description})")
    void insert(DeptLog deptLog);
}

数据库表

dept_log 日志表
create table dept_log(
   	id int auto_increment comment '主键ID' primary key,
    create_time datetime null comment '操作时间',
    description varchar(300) null comment '操作描述'
)comment '部门操作日志表';

实体类

DeptLog
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptLog {
    private Integer id;
    private LocalDateTime createTime;
    private String description;
}

AOP

概述

AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。

入门案例

需求

统计各个业务层方法执行耗时。

步骤

1.导入AOP依赖

2.编写AOP程序,统计各个业务层方法耗时

代码实现

TimeAspect

package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect//切面注解,表示该类为切面类
@Slf4j
public class TimeAspect {
    @Around("execution(* com.itheima.service.*.*(..))")//切入点表达式,指定目标对象为service包下所有方法
    public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
        //记录开始时间
        long start = System.currentTimeMillis();

        //执行原始方法
        Object result = pjp.proceed();

        //记录结束时间,计算方法耗时
        long end = System.currentTimeMillis();
        log.info(pjp.getSignature()+"执行耗时:{}ms",end-start);

        return result;
    }
}

AOP通知

package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * Spring中的AOP通知Advice
 * 通知指的是为目标方法所编写的重复代码,这些代码被抽取成了一个方法
 * 通知类型如下:
 * @Before ,@Around ,@After ,@AfterReturning ,@AfterThrowing
 */
@Slf4j
@Component
@Order(2)
//@Aspect//切面=通知+切入点
public class MyAspect1 {

    //切入点方法(公共的切入点表达式)
    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    private void pt(){}

    //前置通知,在切入方法执行前执行
    @Before("pt()")//引用切入点
    public void before(){
        log.info("before...");
    }

    //环绕通知,在切入方法执行前后都执行
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();

        //原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了
        log.info("around after");

        return result;
    }

    //后置通知,在切入方法执行后执行,无论是否出现异常
    @After("pt()")
    public void after(){
        log.info("after...");
    }

    //返回后通知,(程序在正常执行的情况下,会执行的后置通知)
    @AfterReturning("pt()")
    public void afterReturning(){
        log.info("afterReturning");
    }

    //异常通知(程序在出现异常的情况下,执行的后置通知)
    @AfterThrowing("pt()")
    public void afterThrowing(){
        log.info("afterThrowing");
    }
}

AOP通知顺序

package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * Spring中的AOP通知顺序
 * 1. 不同的切面类当中,默认情况下通知的执行顺序是根据切面类的类名字母顺序
 * 2. 可以在切面类上面加上@Order注解,来控制不同的切面类通知的执行顺序
 */
@Slf4j
@Component
//@Aspect注释掉此注解,类中通知将不再生效
@Order(1)//切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)
public class MyAspect2 {

    //切入点方法(公共的切入点表达式)
    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    private void pt(){}

    //前置通知,在切入方法执行前执行
    @Before("pt()")//引用切入点
    public void before(){
        log.info("before...");
    }

    //环绕通知,在切入方法执行前后都执行
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();

        //原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了
        log.info("around after");

        return result;
    }

    //后置通知,在切入方法执行后执行,无论是否出现异常
    @After("pt()")
    public void after(){
        log.info("after...");
    }

    //返回后通知,(程序在正常执行的情况下,会执行的后置通知)
    @AfterReturning("pt()")
    public void afterReturning(){
        log.info("afterReturning");
    }

    //异常通知(程序在出现异常的情况下,执行的后置通知)
    @AfterThrowing("pt()")
    public void afterThrowing(){
        log.info("afterThrowing");
    }
}

AOP连接点

package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Spring中的AOP连接点JoinPoint
 * 连接点指的是可以被AOP控制的方法
 */
@Slf4j
@Component
//@Aspect
public class MyAspect3 {

    //切入点方法(公共的切入点表达式)
    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    private void pt(){}

    //环绕通知,在切入方法执行前后都执行
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before...");

        /*
        仅在环绕通知中,获取连接点信息使用的是ProceedingJoinPoint类型,
        在其他通知类型中,获取连接信息的连接点类型为:JoinPoint
         */
        //获取目标类名
        final String className = proceedingJoinPoint.getTarget().getClass().getName();
        log.info("目标类名:{}"+className);
        //获取目标方法签名
        final Signature methodSignature = proceedingJoinPoint.getSignature();
        log.info("目标方法签名:{}"+methodSignature);
        //获取目标方法名
        final String methodName = proceedingJoinPoint.getSignature().getName();
        log.info("目标方法名:{}"+methodName);
        //获取方法执行时需要的参数
        final Object[] args = proceedingJoinPoint.getArgs();
        log.info("方法参数:{}"+ Arrays.toString(args));

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();
        log.info("目标方法的返回值:{}"+result);

        //原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了
        log.info("around after");

        return result;
    }

    //前置通知,在切入方法执行前执行
    @Before("pt()")//引用切入点
    public void before(JoinPoint joinPoint){
        //获取目标类名
        final String className = joinPoint.getTarget().getClass().getName();
        log.info("目标类名:{}"+className);
        //其他API与环绕通知相同
        log.info("before...");
    }
}

AOP切入点表达式

切入点表达式execution

package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Spring中的AOP切入点表达式execution
 * 切入点指的是用于匹配连接点的条件,通知只会在目标方法执行时被应用
 * 语法:execution(访问修饰符? 返回值类型 包名.类名?方法名(方法参数) throws 异常?)
 * 其中访问修饰符可省略,包名.类名亦可省略但不建议省略(可能导致无法精确匹配目标对象)
 * 若方法声明中定义了抛出异常则需要加上抛出异常
 * 通配符:
 * 1."*",单个独立的任意符号,可通配单个返回值,包名,类名,方法名,方法参数
 * 也可以通配包名,类名,方法名的一部分
 * 2."..",多个连续的任意符号,可以通配任意层级的包,或者任意类型,任意个数的参数
 * 根据业务需要,可以使用&&,||,!来组合较为复杂的切入点表达式
 * execution(* com.itheima.service.DeptService.list(..)) || execution(* com.itheima.service.DeptService.delete(..))
 */
@Slf4j
@Component
//@Aspect
public class MyAspect4 {

    /*省略访问修饰符,方法参数应使用全类名
    execution(void com.itheima.service.impl.DeptServiceImpl.deleteById(java.lang.Integer))
    使用*通配返回值类型,表示返回任意类型
    excution(* com.itheima.service.impl.DeptServiceImpl.deleteById(java.lang.Integer))
    使用*通配包名
    excution(* com.*.service.impl.DeptServiceImpl.deleteById(java.lang.Integer))
    使用*通配类名
    excution(* com.*.service.impl.*.deleteById(java.lang.Integer))
    使用..省略包名
    excution(* com..*.deleteById(java.lang.Integer))
    使用*通配方法名
    excution(* com..*.*(java.lang.Integer))
    使用*通配方法名的一部分
    excution(* com..*.delete*(java.lang.Integer))
    使用*通配方法参数,一个*通配一个参数
    excution(* com..*.deleteById(*))
    使用..通配方法参数
    excution(* com..*.deleteById(..))
    */
    //切入点方法(公共的切入点表达式)
    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*())")
    private void pt(){}

    //环绕通知,在切入方法执行前后都执行
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();
        log.info("目标方法的返回值:{}"+result);

        //原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了
        log.info("around after");

        return result;
    }
}

切入点表达式@annotation

package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * Spring中的AOP切入点表达式@annotation
 * 定义自定义注解
 * 在连接点方法上添加自定义的注解
 */
@Slf4j
@Component
//@Aspect
public class MyAspect5 {

    //切入点方法(公共的切入点表达式)
    @Pointcut("@annotation(com.itheima.aop.MyLog)")
    private void pt(){}

    //环绕通知,在切入方法执行前后都执行
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();
        log.info("目标方法的返回值:{}"+result);

        //原始方法如果执行时有异常,环绕通知中的后置代码不会在执行了
        log.info("around after");

        return result;
    }
}

自定义注解

package com.itheima.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}

DeptServiceImpl

package com.itheima.service.impl;

import com.itheima.aop.MyLog;
import com.itheima.mapper.DeptMapper;
import com.itheima.pojo.Dept;
import com.itheima.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;

    @Override
    public List<Dept> list() {
        List<Dept> deptList = deptMapper.list();
        return deptList;
    }

    @MyLog//自定义注解,表示当前方法为目标方法
    @Override
    public void delete(Integer id) {
        //1. 删除部门
        deptMapper.delete(id);
    }

    @MyLog
    @Override
    public void save(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.save(dept);
    }

    @Override
    public Dept getById(Integer id) {
        return deptMapper.getById(id);
    }

    @MyLog
    @Override
    public void update(Dept dept) {
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.update(dept);
    }
}

AOP案例

需求

将案例中增、删、改相关接口的操作日志记录到数据库表中

代码实现

数据库表

-- 操作日志表
create table operate_log(
    id int unsigned primary key auto_increment comment 'ID',
    operate_user int unsigned comment '操作人',
    operate_time datetime comment '操作时间',
    class_name varchar(100) comment '操作的类名',
    method_name varchar(100) comment '操作的方法名',
    method_params varchar(1000) comment '方法参数',
    return_value varchar(2000) comment '返回值',
    cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';

切面类OperateAspect

package com.itheima.aop;

import com.alibaba.fastjson.JSONObject;
import com.itheima.mapper.OperateLogMapper;
import com.itheima.pojo.OperateLog;
import com.itheima.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

@Aspect
@Slf4j
@Component
public class OperateAspect {
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private OperateLogMapper operateLogMapper;

    @Around("@annotation(com.itheima.anno.MyLog)")
    public Object recordLog(ProceedingJoinPoint pjp) throws Throwable {

        //获取请求头中的jwt令牌
        String token = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(token);
        //获取操作人id
        Integer operateUser = (Integer) claims.get("id");
        //操作时间
        LocalDateTime operateTime = LocalDateTime.now();
        //获取目标类名
        String className = pjp.getTarget().getClass().getName();
        //获取方法名
        String methodName = pjp.getSignature().getName();
        //获取方法参数
        String methodParams = Arrays.toString(pjp.getArgs());

        //记录开始时间
        long begin = System.currentTimeMillis();

        //执行原始方法
        Object result = pjp.proceed();

        //记录结束时间
        long end = System.currentTimeMillis();

        /*
        将对象转换为字符串,使用的是阿里巴巴的json和对象转换工具
        导入依赖即可使用
        
            com.alibaba
            fastjson
            1.2.76
        
        */
        String resultValue = JSONObject.toJSONString(result);
        //计算消耗时间
        long costTime = end - begin;

        //构建日志对象
        OperateLog operateLog = new OperateLog(null, operateUser, operateTime, className,
                methodName, methodParams, resultValue, costTime);
        //记录日志
        operateLogMapper.insert(operateLog);
        log.info("AOP记录操作日志: {}" , operateLog);

        return result;
    }
}

OperateLogMapper

package com.itheima.mapper;

import com.itheima.pojo.OperateLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OperateLogMapper {

    //插入日志数据
    @Insert("insert into operate_log (operate_user, operate_time, class_name, method_name, method_params, return_value, cost_time) " +
            "values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    void insert(OperateLog log);
}

OperateLog操作日志实体类

package com.itheima.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //ID
    private Integer operateUser; //操作人ID
    private LocalDateTime operateTime; //操作时间
    private String className; //操作类名
    private String methodName; //操作方法名
    private String methodParams; //操作方法参数
    private String returnValue; //操作方法返回值
    private Long costTime; //操作耗时
}

自定义注解

package com.itheima.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}

DeptServiceImpl

package com.itheima.service.impl;

import com.itheima.anno.MyLog;
import com.itheima.mapper.DeptMapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Dept;
import com.itheima.pojo.DeptLog;
import com.itheima.service.DeptLogService;
import com.itheima.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private DeptLogService deptLogService;

    @Override
    public List<Dept> list() {
        //调用mapper层的list方法
        List<Dept> deptList = deptMapper.list();
        return deptList;
    }

    @MyLog
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Integer id) throws Exception {
        try {
            //调用mapper层的deleteById方法
            deptMapper.deleteById(id);

            //删除该部门员工
            empMapper.deleteByDeptId(id);
        } finally {
            //无论是否成功都要记录部门日志
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,此次解散的是:"+id+"号部门");
            //开启了新的事务
            deptLogService.insert(deptLog);
        }
    }

    @MyLog
    @Override
    public void insert(Dept dept) {
        //设置创建时间与更新时间
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        //调用mapper层的insert方法
        deptMapper.insert(dept);
    }

    @Override
    public Dept selectById(long id) {
        //调用mapper层的selectById方法
        Dept dept = deptMapper.selectById(id);
        return dept;
    }

    @MyLog
    @Override
    public void update(Dept dept) {
        //设置更新时间
        dept.setUpdateTime(LocalDateTime.now());
        //调用mapper层的update方法
        deptMapper.update(dept);
    }
}

你可能感兴趣的:(java,spring,mybatis)