mybatis-plus

129 阅读13分钟

事务

事务是用户定义的一个操作序列。事务认为,这些操作序列是一个不可分割的工作单位。

事务有四个特点:原子性、一致性、隔离性和持久性

事务的原子性:表示事务执行过程中,用户定义的操作序列要么全部执行成功,要么全部执行失败。

事务的一致性:表示当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态,这称为事务回滚。

事务的隔离性:表示在事务的执行过程中对数据的修改,在事务提交之前对其他事务不可见。

事务的持久性:表示事务完成之后,对系统的影响是永久性的,如果已经提交的数据在事务执行失败时,数据的状态都应该是正确的。

使用事务时,要求数据库的存储引擎必须是innoDB引擎。

事务的实现方式

1、保证一个业务的所有更新操作中,所使用的连接对象为同一个连接对象

2、将连接对象的提交方式设置为手动提交

通过con.commit()提交事务

如果有异常发生时,可以通过con.rollback()回滚事务。

con.setAutoCommit(false)//设置手动提交方式
con.commit()//提交事务
con.rollback()//回滚事务

事务的并发问题

当两个或两个以上的线程,同时访问同一条记录时,就存在事务的并发问题,可能造成数据混乱。

脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。

不可重复读:事务A多次读取同一个数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。

幻读:事务A对数据库的数据进行批量操作,事务B完成记录的添加,这是新加的记录可能就没有进行事务A的批量操作,这就是幻读。

解决事务的并发问题,需要采用事务隔离级别来进行

事务隔离级别

READ_UNCOMMITTED:未提交读,该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据,该级别不能放在脏读,不可重复读和幻读。

READ_COMMITTED:提交读,该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读。

REPETABLE_READ:可重复读,该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同,该级别可以防止脏读和不可重复读。

SERIALIZABLE:串行读:所有事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读,不可重复已经幻读。但是这将严重影响程序的性能。

事务隔离级别是指若干个并发的事务之间的隔离程度

@Transactional注解的isolation属性,用于定义事务隔离级别。

@Transactional(isolation = Isolation.READ_COMMITTED)

isolation = Isolation.READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读。

isolation = Isolation.READ_COMMITTED
isolation = Isolation.SERIALIZABLE

所有事务一次诸葛执行,这样事务就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响陈旭的性能。

该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读。

面向切面编程

代理模式:在目标方法执行前或执行后,添加非功能性逻辑。

代理模式分为静态代理和动态代理

面向切面编程,是一种通过预编译方式和运行期间,动态代理实现程序功能的统一维护的技术。

面向切面编程的实现,是代理模式来进行的。代理模式可以针对某个目标对象进行代理,在目标对象执行方法前,或执行方法后,添加非功能性业务操作。

Spring AOP

Spring AOP对动态代理进行了封装,Spring AOP框架将分散在系统中的功能块放到一个地方一切面。

AOP术语:

切面(Aspect):就是你要实现的交叉的非核心业务功能

连接点(Joinpoint):应用程序执行过程中插入切面的地点,可以是方法的调用,异常抛出

通知(Advice):通知切面的实际实现代码

切入点(Poincut):定义通知应用在哪些连接点

目标对象(Target):被通知对象

代理(Proxy):将通知应用到目标对象后创建的对象

织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程

通知类型:

前置通知:在目标方法执行前,添加非功能性业务。

后通知:在目标方法执行后,添加非功能性业务。

环绕通知:在目标方法执行前,执行后,添加非功能性业务。

抛出异常通知:在目标方法抛出异常是,添加非功能性业务。

package com.project.util;
​
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
​
@Component
@Aspect//标识该类为切面类
public class CutUtil {
//    第一个* 表示方法的任意返回类型
//    com.project.service..表示匹配指定包集子包中的类
//    *.* 匹配任意类的任意方法
//    (..)匹配方法任何参数//    @Before表示com.project.service包中所有的类,在执行所有方法时,都会调用该方法。
    @Before("execution(* com.project.service..*.*(..))")
    public void before(){
        System.out.println("before前置通知");
    }
​
    @After("execution(* com.project.service..*.*(..))")
    public void after(){
        System.out.println("after后通知");
    }
    @Around("execution(* com.project.service..*.*(..))")
    public Object around(ProceedingJoinPoint point){
        System.out.println("环绕前");
        //得到目标对象
        Object target=point.getTarget();
        try {
            //执行目标方法,得到方法执行后的返回值
            Object returnObj=point.proceed();
            System.out.println("环绕后");
            return returnObj;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }
​
    @AfterThrowing(value = "execution(* com.project.service..*.*(..))",
            throwing = "e")
    public void throwException(JoinPoint point,Exception e){
//        得到目标对象
        Object target=point.getTarget();
//        得到执行目标方法名
        String methodName=point.getSignature().toString();
​
        System.out.println("执行"+target.getClass().getSimpleName()+"的"+methodName+
                "方法,抛出"+e.getClass().getSimpleName()+"异常");
    }
}

Aop的环境搭建

1、导入依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>5.2.19.RELEASE</version>
</dependency>

2、创建目标接口和目标对象

接口

public interface IUserService {
    public void add();
    public void del();
    public void update();
}

实现类

@Service
public class UserServiceImpl implements IUserService {
    @Override
    public void add() {
        System.out.println("user的添加");
    }
​
    @Override
    public void del() {
        System.out.println("user的删除");
    }
​
    @Override
    public void update() {
        System.out.println("user的修改");
    }
}

3、创建切面类

package com.project.util;
​
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
​
@Component
@Aspect//标识该类为切面类
public class CutUtil {
//    第一个* 表示方法的任意返回类型
//    com.project.service..表示匹配指定包集子包中的类
//    *.* 匹配任意类的任意方法
//    (..)匹配方法任何参数//    @Before表示com.project.service包中所有的类,在执行所有方法时,都会调用该方法。
    @Before("execution(* com.project.service..*.*(..))")
    public void before(){
        System.out.println("before前置通知");
    }
​
    @After("execution(* com.project.service..*.*(..))")
    public void after(){
        System.out.println("after后通知");
    }
    @Around("execution(* com.project.service..*.*(..))")
    public Object around(ProceedingJoinPoint point){
        System.out.println("环绕前");
        //得到目标对象
        Object target=point.getTarget();
        try {
            //执行目标方法,得到方法执行后的返回值
            Object returnObj=point.proceed();
            System.out.println("环绕后");
            return returnObj;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }
​
    @AfterThrowing(value = "execution(* com.project.service..*.*(..))",
            throwing = "e")
    public void throwException(JoinPoint point,Exception e){
//        得到目标对象
        Object target=point.getTarget();
//        得到执行目标方法名
        String methodName=point.getSignature().toString();
​
        System.out.println("执行"+target.getClass().getSimpleName()+"的"+methodName+
                "方法,抛出"+e.getClass().getSimpleName()+"异常");
    }
}

4、创建配置类

package com.project.config;
​
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
​
@Configuration //标识该类为配置类
@ComponentScan("com.project") //扫描指定包及子包中的spring组件类
@EnableAspectJAutoProxy //添加自动代理
public class AopConfig {
}

5、创建测试类

package com.project;
​
import com.project.config.AopConfig;
import com.project.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
​
public class AopTest {
    public static void main(String[] args) {
        //加载配置类,创建spring上下文
        ApplicationContext context=new AnnotationConfigApplicationContext(AopConfig.class);
        IUserService service=context.getBean(IUserService.class);
        service.del();
        service.add();
        service.update();
    }
}

MyBatis-Plus

官网:www.baomidou.com/

MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。

连接池

传统开发中,每一次请求都要建立一次数据库连接,每一次数据库连接,使用完后都得断开。频繁的数据库连接操作势必占用很多的系统资源,响应速度必定下降。另外,在高并发时,系统资源被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

解决方案:为数据库连接建立一个“缓冲池”(连接池)。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去,通过设定连接池的最大连接数来防止系统无休止的数据库连接。

连接池的工作流程:当客户端请求服务器,服务器需要使用连接对象操作数据库的数据,这时,需要从连接池中申请一个连接对象。连接池会分配一个空闲连接给该客户,如果连接池中没有空闲连接,就看没有有达到最大连接数,如果没有到达最大连接数,就创建新连接分配给客户。如果已经到达最大连接数,那么,请求用户会等待一段时间,再等待时间内,如果有连接对象被释放,则分配给等待用户,等待时间结束后,还没有连接被释放,则返回null。

MyBatis-Plus环境搭建

1、导入依赖

父包

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.7</version>
​
    <relativePath/>
</parent>

依赖包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.9</version>
</dependency>

2、创建实体类

package com.project.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.time.LocalDate;
//声明该实体类映射的表名
@TableName("t_product")
public class ProductBean {
    //表示该列为主键列,value 表示该列映射列名
    //type = IdType.AUTO 表示该列的值使用自动增长列生成
    @TableId(value = "pk_productId",type = IdType.AUTO)
    private Integer id;
    //指定当前属性映射的列名
    @TableField("p_name")
    private String name;
    @TableField("p_createDate")
    private LocalDate createDate;
    @TableField("p_price")
    private Integer price;
}

3、配置文件资源

在resources目录下,创建application.yml配置文件

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver   #定义配置驱动类
    username: root   #mysql登陆用户名
    password: root   #mysql登陆密码
    url: jdbc:mysql://localhost:12345/mydb?characterEncoding=utf8&allowMultiQueries=true
    type: com.alibaba.druid.pool.DruidDataSource   #配置连接池
    druid:
      one:
        max-active: 100   #最大连接数
        min-idle: 20    #最小连接数
        max-wait: 2000   #超时时间(毫秒)


mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   #配置日志
  type-aliases-package: com.project.bean    #实体类所在的包,允许用实体类的类名做别名
  mapper-locations: classpath:*/*Mapper.xml   #链接mapper文件

4、创建业务接口

package com.project.service;

import com.project.bean.ProductBean;

import java.time.LocalDate;
import java.util.List;

public interface IProductService {
    public void add(ProductBean productBean);

    public void del(Integer id);

    public void update(Integer id,Integer price);

    public List<ProductBean> findAll();

    public ProductBean findById(Integer id);

    public List<ProductBean> findByItem(String name, LocalDate startDate,LocalDate endDate);
}

5、创建mapper接口

package com.project.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.project.bean.ProductBean;
import org.apache.ibatis.annotations.Mapper;

@Mapper //标识为mapper接口
public interface IProductMapper extends BaseMapper<ProductBean> {

}

6、书写业务接口实现类

package com.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.project.bean.ProductBean;
import com.project.mapper.IProductMapper;
import com.project.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

@Service
@Transactional //该类中所有的方法支持事务
public class ProductServiceImpl implements IProductService {
    @Autowired
    private IProductMapper mapper;
    @Override
    /**
     * 添加
     */
    public void add(ProductBean productBean) {
        mapper.insert(productBean);
    }

    @Override
    /**
     * 按id删除
     */
    public void del(Integer id) {
        mapper.deleteById(id);
    }

    @Override
    /**
     * 按id修改价格
     */
    public void update(Integer id, Integer price) {
        ProductBean productBean=new ProductBean();
        productBean.setId(id);
        productBean.setPrice(price);
        mapper.updateById(productBean);

    }

    @Override
    /**
     * 查找所有
     */
    public List<ProductBean> findAll() {
        return mapper.selectList(null);
    }

    @Override
    /**
     * 按id查询商品
     */
    public ProductBean findById(Integer id) {
        return mapper.selectById(id);
    }

    @Override
    /**
     * 动态条件查询
     * like 模糊查询
     * ge 大于等于
     * le 小于等于
     * selectList()查询条件
     */
    public List<ProductBean> findByItem(String name, LocalDate startDate, LocalDate endDate) {
        QueryWrapper<ProductBean> qw=new QueryWrapper<>();
        if (name!=null && name.length()!=0){
            qw.like("p_name",name);
        }
        if (startDate!=null){
            qw.ge("p_createDate",startDate);
        }
        if (endDate!=null){
            qw.le("p_createDate",endDate);
        }

        return mapper.selectList(qw);
    }
}

7、测试类

package com.project;

import com.project.bean.ProductBean;
import com.project.service.IProductService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.time.LocalDate;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Main.class)//启动类类模板
public class ProductMain {
    @Autowired
    private IProductService service;
    @Test
    public void test(){
//        service.add(new ProductBean("百事可乐", LocalDate.parse("2022-05-07"),6));
//        service.del(27);
//        service.update(29,10);
//        System.out.println(service.findAll());
//        System.out.println(service.findById(29));
        System.out.println(service.findByItem("电",LocalDate.parse("2022-05-01"),LocalDate.parse("2022-05-20")));
    }

}

分页查询

1、创建配置类

定义数据库SQL语句的方言,mybatis会根据配置的方言,产生分页SQL语句。

@Configuration
public class MyBatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(
                new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

2、书写启动类

@SpringBootApplication
public class PlusMain {
    public static void main(String[] args) {
        SpringApplication.run(PlusMain.class);
    }
}

3、定义业务接口方法

 /**
     * 动态条件分页查询
     * @param pageNo 页码
     * @param name 商品名
     * @param startDate 生产日期
     * @param endDate 结束日期
     * @return 商品分页集合
     */
    public IPage<ProductBean> findByItem(Integer pageNo, String name, LocalDate startDate,LocalDate endDate);

4、定义mapper接口

@Mapper
public interface IProductMapper extends BaseMapper<ProductBean> {
}

5、书写业务方法

@Override
public IPage<ProductBean> findByItem(Integer pageNo, String name, LocalDate startDate, LocalDate endDate) {
    QueryWrapper<ProductBean> qw=new QueryWrapper<>();
    if (name!=null && name.length()!=0){
        qw.like("p_name",name);
    }
    if (startDate!=null){
        qw.ge("p_createDate",startDate);
    }
    if (endDate!=null){
        qw.le("p_createDate",endDate);
    }

    return mapper.selectPage(new Page(pageNo,3),qw);
}

6、写测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = PlusMain.class)
public class Test {
    @Autowired
    private IProductService service;
    @org.junit.Test
    public void test(){
        IPage ip=service.findByItem(1,"",null,null);
        System.out.println(ip.getRecords()+""//得到当前数据
                +ip.getCurrent()+""//得到页码
                +ip.getPages()+""+//总页数
                ip.getTotal()+""//得到总记录数
                +ip.getSize());//得到每页显示的记录数
    }
}

Mapper-plus关联操作

一对多

1、创建实体类

部门

import java.util.List;
@TableName("t_dept")
public class DeptBean {
    @TableId(value = "pk_deptId",type = IdType.AUTO)
    private Integer id;
    @TableField("d_name")
    private String name;
    /**统计部门中员工的数量*/
    @TableField(exist = false)//标识该属性没有对应的列
    private Integer emNum;
    @TableField(exist = false)
    private List<EmployeeBean> emList;
}

员工

@TableName("t_dept")
public class DeptBean {
    @TableId(value = "pk_deptId",type = IdType.AUTO)
    private Integer id;
    @TableField("d_name")
    private String name;
    /**统计部门中员工的数量*/
    @TableField(exist = false)//标识该属性没有对应的列
    private Integer emNum;
    @TableField(exist = false)
    private List<EmployeeBean> emList;
}

需要注意,如果一个属性没有对应的列,必须加上@TableField(exist = false),否则,mybatis-plus会认为数据库表中有一个和该属性同名列。

2、建立业务接口

部门业务接口

package com.project.service;

import com.project.bean.DeptBean;
import com.project.bean.EmployeeBean;

import java.util.List;

public interface IDeptService {
    /**
     * 查询所有的部门,同时统计每个部门的人数
     * @return 部门集合
     */
    public List<DeptBean> findAll();

    /**
     * 添加部门,同时添加该部门的员工集合
     * @param deptBean 部门对象
     * @param emList 新员工集合
     */
    public void add(DeptBean deptBean, List<EmployeeBean> emList);

    /**
     * 删除部门,同时级联删除该部门的员工
     * @param id 部门id
     */
    public void delCasede(Integer id);

    /**
     * 删除部门,同时将该部门员工的外键设置为null
     * @param id 部门id
     */
    public void delSetNull(Integer id);

    /**
     * 按id查询部门,同时查询该部门中所有的员工
     * @param id 部门id
     * @return 部门对象
     */
    public DeptBean findById(Integer id);
}

员工业务接口

package com.project.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.project.bean.EmployeeBean;

public interface IEmployeeService {
    /**
     * 添加员工
     * @param employeeBean 员工对象
     */
    public void add(EmployeeBean employeeBean);

    /**
     * 动态条件分页查询,同时查询每个员工所在部门名称
     * @param pageNo 页码
     * @param deptName 部门名称
     * @param name 员工姓名
     * @return 分页对象
     */
    public IPage<EmployeeBean> findByItem(Integer pageNo,String deptName,String name);

    /**
     * 按id查询员工,同时查询员工的部门信息
     * @param id 员工编号
     * @return 员工对象
     */
    public EmployeeBean findById(Integer id);

}

3、建立mapper接口

部门mapper

package com.project.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.project.bean.DeptBean;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface IDeptMapper extends BaseMapper<DeptBean> {
    @Select("SELECT d.*,COUNT(e.pk_empId) emNum FROM t_dept d LEFT JOIN t_employee e ON d.pk_deptId=e.fk_deptId GROUP BY d.pk_deptId")
    @ResultMap("deptMap")
    public List<DeptBean> findAll();
    @Delete("delete from t_employee where fk_deptId=#{id};"+
            "delete from t_dept where pk_deptId=#{id};")
    public void delCasede(Integer id);

    @Delete("update t_employee set fk_deptId=null where fk_deptId=#{id};"+
            "delete from t_dept where pk_deptId=#{id};")
    public void delSetNull(Integer id);

}

员工mapper

package com.project.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.bean.EmployeeBean;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface IEmployeeMapper extends BaseMapper<EmployeeBean> {
    public void addMore(@Param("deptId") Integer deptId, @Param("emList") List<EmployeeBean> employeeBeanList);
    public IPage<EmployeeBean> findByItem(Page page, @Param("deptName") String deptName,@Param("name") String name);
}

对于联表查询的结果集,动态条件查询、循环,都需要在mapper文件中完成

4、书写mapper文件

部门IDeptMapper

<mapper namespace="com.project.mapper.IDeptMapper">
    <resultMap id="deptMap" type="DeptBean">
        <id property="id" column="pk_deptId"></id>
        <result property="name" column="d_name"></result>
        <result property="emNum" column="emNum"></result>
    </resultMap>
</mapper>

员工IEmployeeMapper

<mapper namespace="com.project.mapper.IEmployeeMapper">
    <insert id="addMore">
        insert into t_employee(e_name,e_birthday,e_job,fk_deptId) values
        <foreach collection="emList" item="em" separator=",">
            (#{em.name},#{em.birthday},#{em.job},#{deptId})
        </foreach>
    </insert>

    <resultMap id="emMap" type="EmployeeBean">
        <id property="id" column="pk_empId"></id>
        <result property="name"  column="e_name"></result>
        <result property="job"  column="e_job"></result>
        <result property="birthday"  column="e_birthday"></result>
        <result property="dept.name"  column="d_name"></result>
    </resultMap>

    <select id="findByItem" resultMap="emMap">
        select e.*,d.d_name from t_dept d,t_employee e where d.pk_deptId=e.fk_deptId
        <if test="deptName!=null and deptName!=''">
            and d.d_name like "%"#{deptName}"%"
        </if>
        <if test="name!=null and name!=''">
            and e.e_name like "%"#{name}"%"
        </if>
    </select>
</mapper>

5、书写业务方法

部门业务方法

package com.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.project.bean.DeptBean;
import com.project.bean.EmployeeBean;
import com.project.mapper.IDeptMapper;
import com.project.mapper.IEmployeeMapper;
import com.project.service.IDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
@Service
@Transactional
public class DeptServiceImpl implements IDeptService {
    @Autowired
    private IDeptMapper deptMapper;

    @Autowired
    private IEmployeeMapper employeeMapper;

    @Override
    public List<DeptBean> findAll() {
        return deptMapper.findAll();
    }

    @Override
    public void add(DeptBean deptBean, List<EmployeeBean> emList) {
        deptMapper.insert(deptBean);
        employeeMapper.addMore(deptBean.getId(),emList);
    }

    @Override
    public void delCasede(Integer id) {
        deptMapper.delCasede(id);
    }

    @Override
    public void delSetNull(Integer id) {
        deptMapper.delSetNull(id);

    }

    @Override
    public DeptBean findById(Integer id) {
        DeptBean deptBean=deptMapper.selectById(id);
        QueryWrapper<EmployeeBean> qw=new QueryWrapper<>();
        qw.eq("fk_deptId",id);
        deptBean.setEmList(employeeMapper.selectList(qw));
        return deptBean;
    }
}

员工业务方法

package com.project.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.bean.EmployeeBean;
import com.project.mapper.IDeptMapper;
import com.project.mapper.IEmployeeMapper;
import com.project.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class EmployeeServiceImpl implements IEmployeeService {
    @Autowired
    private IEmployeeMapper employeeMapper;
    @Autowired
    private IDeptMapper deptMapper;
    @Override
    public void add(EmployeeBean employeeBean) {
        employeeMapper.insert(employeeBean);
    }

    @Override
    public IPage<EmployeeBean> findByItem(Integer pageNo, String deptName, String name) {

        return employeeMapper.findByItem(new Page(pageNo,3),deptName,name);
    }

    @Override
    public EmployeeBean findById(Integer id) {
        EmployeeBean em=employeeMapper.selectById(id);
        em.setDept(deptMapper.selectById(em.getDeptId()));
        return em;
    }
}

6、书写测试类

部门测试类

package com.project;

import com.project.bean.DeptBean;
import com.project.bean.EmployeeBean;
import com.project.service.IDeptService;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = EmMain.class)
public class Test {

    @Autowired
    private IDeptService service;
    @org.junit.Test
    public void test(){
//        System.out.println(service.findAll());
//        List<EmployeeBean> list=new ArrayList<>();
//        list.add(new EmployeeBean("王芳","职员", LocalDate.parse("1998-02-23")));
//        list.add(new EmployeeBean("刘芳","职员", LocalDate.parse("1997-02-23")));
//        service.add(new DeptBean("市场部"),list);
//        service.delCasede(4);
//        service.delSetNull(5);
//        System.out.println(service.findById(1));
    }

}

员工测试类

package com.project;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.bean.EmployeeBean;
import com.project.service.IEmployeeService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = EmMain.class)
public class EmployeeTest {
    @Autowired
    private IEmployeeService service;
    @Test
    public void test(){
//        service.add(new EmployeeBean("刘三姐","职员", LocalDate.parse("1997-01-12"),3));
//        System.out.println(service.findById(13));
        IPage ip=service.findByItem(1,null,null);
        System.out.println(ip.getRecords());
    }

}

统计查询记录数

public boolean delete(Integer id) {
    QueryWrapper<StudentBean> qw=new QueryWrapper<>();
    qw.eq("fk_classId",id);
    Integer num=studentMapper.selectCount(qw);
   if (num==0){
       classMapper.deleteById(id);
       return true;
   }
    return false;
}

事务传播行为

事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

@Transactional注解的propagation属性,用于定义事务传播行为

@Transactional(propagation = Propagation.REQUIRED)

Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。这是默认值。

Propagation.REQUIRES_NEW:创建一个新事物,如果当前存在事务,则把当前事务挂起

:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式运行。

:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

:以非事务方式运行,如果当前存在事务,则抛出异常。

:如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常。