栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

项目管理——MyBatisPlus

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

项目管理——MyBatisPlus

MyBatisPlus核心技术 一、MyBatisPlus快速开始 1 MyBatisPlus概述

MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatisPlus的愿景是成为MyBatis最好的搭档,就像魂斗罗中的1P、2P,基友搭配,效率翻倍

官方网址:https://mp.baomidou.com/

2 MyBatisPlus准备工作 2.1 前期准备
  • 准备数据表,导入tb_employee.sql文件

  • 创建Maven工程MyBatisPlus

  • 引入Maven依赖

    
        
        
            com.baomidou
            mybatis-plus
            3.4.2
        
        
        
            mysql
            mysql-connector-java
            5.1.47
        
        
        
            org.projectlombok
            lombok
            1.18.20
            provided
        
        
        
            junit
            junit
            4.12
            test
        
        
        
            com.alibaba
            druid
            1.2.6
        
        
        
            log4j
            log4j
            1.2.17
        
        
        
            org.springframework
            spring-context
            5.3.9
        
        
            org.springframework
            spring-orm
            5.3.9
        
   
    
  • 在com.bzcxy.pojo下创建相关实体类(JavaBean)
@Data 
public class Employee { 
	private Integer id; 
	private String empName; 
	private String useremail; 
	private String gender; 
	private Integer age; 
}
2.2 搭建Spring+Mybatis环境
  • Mybatis全局配置文件mybatis-config.xml



    
        
        
    

  • 数据库配置文件jdbc.properties
jdbcusername=root
jdbcpassword=root
jdbcUrl=jdbc:mysql://localhost:3306/baizhan?useSSL=false&useUnicode=true&characterEncoding=utf8
driverClass=com.mysql.jdbc.Driver
  • Spring配置文件applicationContext.xml


    
    
    
    
        
         
       
        
        
       
    
    
    
    
        
        
          
    
    

3 集成MyBatisPlus

调整 SqlSessionFactory 为 MyBatis-Plus 的 SqlSessionFactory
MyBatis的SqlSessionFactory

org.mybatis.spring.SqlSessionFactoryBean

MyBatis-Plus的SqlSessionFactory

com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryB ean

测试

import com.bzcxy.mapper.EmployeeMapper;
import com.bzcxy.mapper.UserMapper;
import com.bzcxy.pojo.Employee;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class AppTest {
    private ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    private UserMapper userMapper = applicationContext.getBean("userMapper",UserMapper.class);
    private EmployeeMapper employeeMapper =
            applicationContext.getBean("employeeMapper",EmployeeMapper.class);
    @Test
    //测试环境
    public void testEnv() throws SQLException {
        //从Spring容器中获取dataSource
        DataSource dataSource = (DataSource) applicationContext.getBean("dataSource");
        //获取链接
        Connection conn = dataSource.getConnection();
        System.out.println(conn);
    }

    @Test
    public void delall()
    {
        userMapper.deleteAll();
    }

    @Test
    public void testlogic()
    {
//        Employee employee = new Employee();
//        employee.setId(2);
//        employee.deleteById();
        Employee employee = new Employee();
        employee.setId(2);
        Employee e = employee.selectById();
        System.out.println(e);
    }

    @Test
    public void testfill()
    {
        Employee employee = new Employee();
        employee.setEmpName("百战程序员");
        employee.setUseremail("baizhan@baizhan.com");
        employee.setAge(3);
        employee.setGender("m");
        employee.insert();
    }

}

二、MyBatisPlus通用CRUD 1 baseMapper

针对employee表进行CRUD

  • 基于MyBatis:
    编写EmployeeMapper接口,并手动编写CRUD方法
    提供EmployeeMapper.xml映射文件,并手动编写每个方法对应的SQL语 句
  • 基于MyBatisPlus
    只需要创建EmployeeMapper接口并继承baseMapper接口,这就是使用
    MyBatisPlus需要完成的所有操作,甚至不需要创建SQL的映射文件
// baseMapper:泛型指定的是所需操作的实体类
//XXMapper继承该接口后,即可获得CRUD功能 不需要XXMapper.xml
public interface EmployeeMapper extends baseMapper {
    void deleteAll();
}
2 通用CRUD 2.1 insert

通过baseMapper的insert方法可以直接传入一个实体类对象进行插入操作

public class CRUDTest {
    private ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    private EmployeeMapper employeeMapper =
            applicationContext.getBean("employeeMapper",EmployeeMapper.class);
    @Test
    public void testInsert() throws SQLException {
        //创建实体类对象
        Employee employee = new Employee();
        //设置相关属性
        employee.setEmpName("MP");
        employee.setUseremail("mp@baizhan.com");
        employee.setGender("m");
        employee.setAge(15);
        //通过baseMapper的insert方法插入数据
        int count = employeeMapper.insert(employee);
        //代表受影响的行数
       // System.out.println(employee.getId());
        //插入成功以后 直接获取主键
        System.out.println(employee.getId());
    }
  }

注: 由于没有主键策略及相关属性不匹配,以上代码会报错

2.2 @TableId

@TableId注解于实体类属性上,用于指定哪个属性为主键

参数:

type主键的策略类型

ASSIGN_UUID 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator
的方法nextUUID(默认default方法)

@Data 
public class Employee { 
	//指定id属性为主键,value是数据表中的主键列名,如果属性名和列名一致,则可以 省略 
	//指定type主键策略为自增的IdType.AUTO 
	@TableId(value = "id",type = IdType.AUTO) 
	private Integer id; 
	private String empName; 
	private String useremail; 
	private String gender; 
	private Integer age; 
}
2.3 @TableName

@TableName注解于实体类上,用于指定该类为哪个表的实体类

@Data 
//mybatisplus 会找跟类名一样的表名 进行查询 
//@TableName指定表名为tb_employee 
@TableName(value = "tb_employee") 
public class Employee { 
	//指定id属性为主键,value是数据表中的主键列名,如果属性名和列名一致,则可以 省略 
	//指定type主键策略为自增的IdType.AUTO 
	@TableId(value = "id",type = IdType.AUTO) 
	private Integer id; 
	private String empName; 
	private String useremail; 
	private String gender; 
	private Integer age; 
}
2.4 @TableField

@TableField注解于实体类非主键属性上,用于在属性和列名不同的情况下,指定映射关系

@Data 
//mybatisplus 会找跟类名一样的表名 进行查询 
//@TableName指定表名为tb_employee 
@TableName(value = "tb_employee")
public class Employee { 
	//指定id属性为主键,value是数据表中的主键列名,如果属性名和列名一致,则可以 省略 
	//指定type主键策略为自增的IdType.AUTO 
	@TableId(value = "id",type = IdType.AUTO) 
	private Integer id; 
	private String empName; 
	//指定useremail属性对应的列名为email 
	@TableField(value = "email") 
	private String useremail; 
	private String gender; 
	private Integer age; 
}

再次执行代码,插入成功!

2.5 全局策略配置

如果针对每一个实体类都要添加相关注解,比较麻烦,可以使用通用的配置进行统一管理。
在applicationContext.xml中配置全局策略,全局配置有多个,在此仅仅配置DB

  
    
        
        
        
        
        
        
       
     

将DBconfig加入GlobalConfig

  
    
        
    

在sqlSessionFactory中添加globalConfig配置

    
        
        
        
        
	        

修改POJO

@Data 
//mybatisplus 会找跟类名一样的表名 进行查询 
//@TableName指定表名为tb_employee 

public class Employee { 
	//指定id属性为主键,value是数据表中的主键列名,如果属性名和列名一致,则可以 省略 
	//指定type主键策略为自增的IdType.AUTO 
	@TableId(value = "id") 
	private Integer id; 
	private String empName; 
	//指定useremail属性对应的列名为email 
	@TableField(value = "email") 
	private String useremail; 
	private String gender; 
	private Integer age; 
}

测试

2.6 获取主键值

MyBatis:需要通过useGenerateKeys,以及KeyProperty来设置

 

MyBatisPlus:自动将主键值回写到实体类对象中

//插入成功以后 直接获取主键 
System.out.println(employee.getId());

2.7 update

通过baseMapper的updateById方法可以直接传入一个实体类对象根据id进行更新没有设置的值则忽略

   @Test
    public void testUpdate()
    {
        //创建实体类对象
        Employee employee = new Employee();
        //设置需要更新的属性
        employee.setEmpName("baizhan");
        employee.setGender("f");
        //设置需要修改的数据id
        employee.setId(5);
        //根据主键进行更新,没有设置的值则忽略
        employeeMapper.updateById(employee);
    }
2.8 delete
  • 通过deleteById方法可以根据id删除一条记录
int deleteById(Serializable id);

//根据主键删除 
//删除11号数据 
employeeMapper.deleteById(11);
  • 通过deleteBatchIds进行批量删除
int deleteBatchIds(@Param("coll") Collection idList);

参数是实现Collection接口的集合

  @Test
    public void testDelete()
    {
        //根据主键删除
        //删除11号数据
       // employeeMapper.deleteById(11);
        //通过deleteBatchIds进行批量删除
        //创建list容器,加入将要删除的元素
        List ids = new ArrayList<>();
        ids.add(12);
        ids.add(13);
        //同时删除12 13
        //employeeMapper.deleteBatchIds(ids);
        Map map = new HashMap<>();
        map.put("emp_name","baizhan");
        map.put("gender","m");
        employeeMapper.deleteByMap(map);
    }
  • 通过deleteByMap进行条件删除
int deleteByMap(@Param("cm") Map columnMap);

根据columnMap的key与value删除,key为列名,value为值,如果有多个key- value键值对,则按照and进行删除

Map map = new HashMap<>(); 
map.put("emp_name","baizhan"); 
//删除emp_name='baizhan'的数据 
employeeMapper.deleteByMap(map);
Map map = new HashMap<>(); 
map.put("emp_name","baizhan"); 
map.put("gender","m"); 
//删除emp_name为baizhan,gender为m的数据 
employeeMapper.deleteByMap(map);
2.9 select
  • 通过selectById根据id获取一条数据
T selectById(Serializable id); 
//根据id查找一条数据,并返回实体类对象 
Employee e = employeeMapper.selectById(1); 
System.out.println(e);
  • 通过selectBatchIds进行批量查询
List selectBatchIds(@Param("coll") Collection idList);

参数是实现Collection接口的集合

 
        //根据id集合查找
        //创建主键集合
        List ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        //根据id = 1 2 3进行查询 返回一个 Employee对象集合
       List emps = employeeMapper.selectBatchIds(ids);
       System.out.println(emps);
  • 通过selectByMap进行条件查询
List selectByMap(@Param("cm") Map columnMap);

根据columnMap的key与value查询,key为列名,value为值,如果有多个key- value键值对,则按照and进行查询

  @Test
    public void testselect()
    {
        //根据id查找一条数据,并返回实体类对象
       // Employee e = employeeMapper.selectById(1);
      //  System.out.println(e);
        //根据id集合查找
        //创建主键集合
        List ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        //根据id = 1 2 3进行查询 返回一个 Employee对象集合
       // List emps = employeeMapper.selectBatchIds(ids);
       // System.out.println(emps);
        Map map = new HashMap<>();
        map.put("gender","m");
        //查询所有gender=m的数据
        List emps =  employeeMapper.selectByMap(map);
        System.out.println(emps);
    }
  • 通过selectPage进行分页查询
IPage selectPage(IPage page, @Param("ew") Wrapper queryWrapper);

page(分页条件):创建Page对象并初始化分页条件

//第0行数据开始取两行数据 
new Page<>(0,2)

queryWrapper(条件构造器):暂且为null

IPage(分页对象):返回的分页结果集、分页数据等

进行分页查询时,需要在sqlSessionFactory中添加分页插件

 
        
            
                
                    
                        
                            
                            
                           
                        
                    
                
            
        

测试

    @Test
    public void testselectPage()
    {
        //分页数据
        Page page = new Page(0,2);
        IPage res = employeeMapper.selectPage(page,null);
        //从分页对象中获取结果集
        List emps = res.getRecords();
        System.out.println(emps);
    }
三、条件构造器 1 QueryWrapper
  • Mybatis-Plus 通过 QueryWrapper 来让用户自由的构建SQL条件,简单便捷,没有额外的负担,能够有效提高开发效率
  • 查询包装器QueryWrapper, 主要用于处理 sql 拼接,排序,实体参数查询等
  • 使用的是数据库字段,不是 Java 属性!
  • 需要给QueryWrapper提供实体类类型
  • 条件参数说明:
2 select
  • selectList
    需要给QueryWrapper提供实体类类型new QueryWrapper()
public class QueryWrapperTest {
    private ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    private EmployeeMapper employeeMapper =
            applicationContext.getBean("employeeMapper",EmployeeMapper.class);
    @Test
    public void testselectList()
    {
        QueryWrapper qw = new QueryWrapper<>();
        //查询性别为女,且年龄小于等于35的数据
        qw.like("gender","f").le("age",35);
      //  List emps = employeeMapper.selectList(qw);
       // System.out.println(emps);
        //查询年龄小于25或者年龄大于30的人
        List emps =  employeeMapper.selectList(new QueryWrapper()
                .lt("age",25)
                .or()
                .gt("age",30));
        System.out.println(emps);
    }
 }
  • selectPage
    @Test
    public void testselectpage()
    {
        //创建分页数据
        Page page = new Page(2,2);
        //获取第二页2条数据,且名字包含老师
        IPage res = employeeMapper.selectPage(page,
                new QueryWrapper().like("emp_name","老师"));
        //通过IPage的getRecords方法获取
        List emps = res.getRecords();
        System.out.println(emps);
    }
3 update
    @Test
    public void testupdate()
    {
        //修改名字包含李且age=32数据
        //修改emp_name=baizhan email=baizhan@baizhan.com
        //创建条件构造器
        QueryWrapper qw = new QueryWrapper<>();
        qw.like("emp_name","李").eq("age",32);
        //创建实体类对象
        Employee employee = new Employee();
        employee.setEmpName("baizhan");
        employee.setUseremail("baizhan@baizhan.com");
        employeeMapper.update(employee,qw);
    }
4 delete
    @Test
    public void testdel()
    {
        //删除age 在30-35之间 且名字包含a数据
        employeeMapper.delete(new QueryWrapper()
                .between("age",30,35)
                .like("emp_name","a"));
    }
5 orderby
  • orderByAsc/orderByDesc:升序/降序方法
    @Test
    public void testOrderby()
    {
        //查询所有老师,按照年龄排序
        //按照年龄升序
//        List emps = employeeMapper.selectList(new QueryWrapper()
//                                    .like("emp_name","老师")
//                                    .orderByAsc("age"));
//        System.out.println(emps);
        List emps = employeeMapper.selectList(new QueryWrapper()
                                    .like("emp_name","老师")
                                    .orderByDesc("age"));
        System.out.println(emps);
    }
四、ActiveRecord

ActiveRecord(活动记录)也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。

ActiveRecord主要思想:

  • 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录
  • 通常表的每个字段在类中都有相应的属性
  • ActiveRecord同时负责把自己持久化(即不通过mapper,依靠实体类本身),在ActiveRecord中封装了对数据库的访问,即CURD
  • 是一种领域模型模式,封装了部分业务逻辑
1 Model

实体类继承Model类之后,能通过实体直接进行CRUD操作,而不需要进行调用Mapper
注:必须存在对应的原始mapper并继承baseMapper并且可以使用的前提下

修改Employee实体类

@Data
//继承Model类 开启AR模式
public class Employee extends Model {

    @TableId(value = "id")
    private Integer id;
    private String empName;
    //指定useremail属性对应的列名为email
    @TableField(value = "email")
    private String useremail;
    private String gender;
    private Integer age;   
    //重写pkVal方法,返回主键
    @Override
    protected Serializable pkVal()
    {
        return this.id;
    }
}
2 insert
public class ARTest {
    private ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    @Test
    public void testinsert()
    {
        Employee employee = new Employee();
        employee.setEmpName("百战程序员");
        employee.setUseremail("baizhan@baizhan.com");
        employee.setAge(3);
        employee.setGender("m");
        //使用AR的insert方法,将实体类自身插入数据库
        employee.insert();
    }
}
3 update
    @Test
    public void testupdate()
    {
        //创建实体类对象
        Employee employee = new Employee();
        employee.setId(15);
        employee.setEmpName("北京尚学堂");
        employee.setUseremail("bjsxt@baizhan.com");
        //使用AR的updateByid,实体类对象将自身更新
        employee.updateById();
    }
4 delete
  • deleteById根据id删除自身
    @Test
    public void testdel()
    {
        //创建实体类对象
        Employee employee = new Employee();
//        employee.setId(15);
//        //通过AR的deletebyid方法 将实体类自身删除
//        employee.deleteById();
        //通过AR的delete方法 参数是条件构造器 删除自身
        employee.delete(new QueryWrapper()
                .like("emp_name","tom"));
    }
  • delete根据条件构造器删除
//通过AR的delete方法 参数是条件构造器 删除自身 
employee.delete(new QueryWrapper() .like("emp_name","tom"));
5 select
  • selectById根据自身id获取数据
    @Test
    public void testselect()
    {
        //创建实体类对象
        Employee employee = new Employee();
 //       employee.setId(2);
        //通过AR的selectByid查询实体类对象
//        Employee e = employee.selectById();
//        System.out.println(e);
        //通过AR的selectAll方法查询所有数据
//        List emps = employee.selectAll();
//        System.out.println(emps);
        //通过AR的selectList方法返回数据 参数是条件构造器
//        List emps =
//                employee.selectList(new QueryWrapper().like("gender","m"));
//        System.out.println(emps);
        //通过AR的selectCount方法返回结果集数量
        int count =
        employee.selectCount(new QueryWrapper().like("emp_name","老师"));
        System.out.println("老师一共有:" + count);
    }
  • selectAll获取所有数据
//通过AR的selectAll方法查询所有数据 
List emps = employee.selectAll();
  • selectList根据条件构造器查询
//通过AR的selectList方法返回数据 参数是条件构造器 
//查询所有性别为m的数据 
List emps = employee.selectList(new QueryWrapper(). like("gender","m"));
  • selectCount根据条件查询结果集数量
//通过AR的selectCount方法返回结果集数量 
//查询所有老师的数量 
int count = employee.selectCount(new QueryWrapper ().like("emp_name","老师"));
五、MyBatisPlus插件机制 1 插件概述

1、 插件机制: Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求,完

成相关数据的动态改变。

  • Executor
    Mybatis的内部执行器,它负责调用StatementHandler操作数据库,并把结果集通过 ResultSetHandler进行自动映射,另外,它还处理了二级缓存的操作,也可以通过插件来实现自定义的二级缓存的。
  • StatementHandler
    Mybatis直接和数据库执行sql脚本的对象。另外它也实现了Mybatis的一级缓存。这里,我们可以使用插件来实现对一级缓存的操作(禁用等等)。
  • ParameterHandler
    Mybatis实现Sql入参设置的对象。插件可以改变我们Sql的参数默认设置。
  • ResultSetHandler
    Mybatis把ResultSet集合映射成POJO的接口对象。我们可以定义插件对Mybatis的结果集自动映射进行修改。

2、 插件原理
四大对象的每个对象在创建时,都会执行interceptorChain.pluginAll(),会经过每个插件对象的 plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行四大对象的方法需要经过代理.

3、常用插件

  • 分页插件
    (com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerI nterceptor)
  • 防止全表更新与删除插件
    (com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInne rInterceptor)
  • 乐观锁插件
    (com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLocke rInnerInterceptor)
2 分页插件

com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor

分页对象使用

public class InterceporTest {
    private ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    @Test
    public void testpage()
    {
        //创建实体类对象
        Employee employee = new Employee();
        //创建分页信息
        Page page = new Page(0,2);

        IPage res = employee.selectPage(page,null);
        //从分页对象中获取记录及
        List emps = res.getRecords();
      //  System.out.println(emps);
        //获取总共记录数
        Long total = page.getTotal();
        System.out.println("total=" + total);
        //获取当前获得了多少数据
        Long size = page.getSize();
        System.out.println("size=" + size);
        //获取一共多少页
        Long pages = page.getPages();
        System.out.println("pages=" + pages);
        //是否有上一页 是否有下一页
        Boolean previous =  page.hasPrevious();
        Boolean next = page.hasNext();
        System.out.println(previous);
        System.out.println(next);
    }
}    
3 防止全表更新与删除插件

com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor

  • 只支持 MySQL5.6.3 以上版本

  • 该插件的作用是分析 DELETE UPDATE 语句,防止小白或者恶意进行 DELETE UPDATE 全表操作

  • 只建议在开发环境中使用,不建议在生产环境使用

  • 在插件的底层 通过 SQL 语句分析命令:Explain 分析当前的 SQL 语句,根据结果集中的 Extra 列来断定当前是否全表操作。

在applicationContext.xml中注册防止全表更新与删除插件插件

 

添加该插件后,如果删除整表,则会抛出异常

   @Test
    public void testdel()
    {
        Employee employee = new Employee();
        employee.delete(null);
    }

4 乐观锁插件

com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor

  • 当要更新一条记录的时候,希望这条记录没有被别人更新
  • 乐观锁的实现原理:
    取出记录时,获取当前 version
    更新时,带上这个 version
    执行更新时, set version = yourVersion+1 where version = yourVersion
    如果 version 不对,就更新失败
  • @Version 用于注解实体属性,必须要有在applicationContext.xml中注册乐观锁插件
 

修改Employee类,添加整型version 属性,并在该属性上面增加@Version

@Data
//继承Model类 开启AR模式
public class Employee extends Model {

    @TableId(value = "id")
    private Integer id;
    private String empName;
    //指定useremail属性对应的列名为email
    @TableField(value = "email")
    private String useremail;
    private String gender;
    private Integer age;
    //实现乐观锁
    @Version
    private Integer version;
    //重写pkVal方法,返回主键
    @Override
    protected Serializable pkVal()
    {
        return this.id;
    }
}

给tb_employee表添加一列整型version并初始化为1

更新数据时会校验版本号,新旧版本号一致时,表示当前数据未被其他事务更新过,更新通
过,版本号自动+1;

   @Test
    public void testversion()
    {
        Employee employee = new Employee();
        employee.setId(2);
        employee.setEmpName("百战程序员");
        //如果版本号跟数据库一致 更新成功,版本号+1
        // 不一致 更新失败
        employee.setVersion(2);
        employee.updateById();
    }
六、MyBatisPlus进阶 1 自定义全局操作

根据 MybatisPlus 的 AbstractSqlInjector可以自定义各种你想要的 sql ,注入到全局中,相当
于自定义 Mybatisplus 自动注入的方法。

导入tb_user.sql,并创建User相关文件

User实体类

@Data
public class User {
    @TableId
    private Integer id;
    private String username;
    private Integer userage;
}

UserMapper类

public interface UserMapper extends baseMapper { 
}

在 Mapper 接口中定义相关的 CRUD 方法

public interface UserMapper extends baseMapper { 
	void deleteAll(); 
}

重写 AbstractMethod的injectMappedStatement方法,实现 Mapper 接口中方法要注入的
SQL

新建com.bzcxy.inject及在包下创建自己的AbstractMethod类(deleteAll)

public class DeleteAll extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement
            (Class mapperClass, Class modelClass, TableInfo tableInfo) {
        //定义sql语句
        String sql = "delete from " + tableInfo.getTableName();
        //方法名
        String method = "deleteAll";
        //构建sqlsource
        SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration,sql,modelClass);
        //通过addDeleteMappedStatement构建
        return this.addDeleteMappedStatement(mapperClass,method,sqlSource);
    }
}

创建自己的AbstractSqlInjector的类(MySqlInject)并重写getMethodList方法

public class MySqlInject extends AbstractSqlInjector {
    @Override
    public List getMethodList(Class mapperClass) {
        List methods = new ArrayList<>();
        //添加自定义方法
        methods.add(new DeleteAll());
        return methods;
    }
}

将MySqlInject注册到全局配置中

    
 
	 
	 
	 

注:需要将防止全表更新与删除插件删除

直接使用deleteAll()

    @Test
    public void delall()
    {
        userMapper.deleteAll();
    }
2 逻辑删除

物理删除:从数据库中直接删除
逻辑删除:在数据库中没有被删除,而是通过一个变量来代表它被删除。

  • logicDeletevalue逻辑删除全局值
  • logicNotDeletevalue 逻辑未删除全局值
  • 在 POJO 的逻辑删除字段 添加 @TableLogic 注解

给tb_employee表添加一列整型deleted并初始化为0

修改Employee类,添加整型deleted属性,并在该属性上面增加@TableLogic

@Data
//继承Model类 开启AR模式
public class Employee extends Model {

    @TableId(value = "id")
    private Integer id;
    private String empName;
    //指定useremail属性对应的列名为email
    @TableField(value = "email")
    private String useremail;
    private String gender;
    private Integer age;
    @Version
    private Integer version;
    //逻辑删除属性
    @TableLogic
    private Integer deleted;
   
    private Date updatetime;
    //重写pkVal方法,返回主键
    @Override
    protected Serializable pkVal()
    {
        return this.id;
    }
}

在applicationContext.xml的DBConfig配置逻辑删除全局值

 
    
        
        
        
        
        
        
        
        
        
        
        
     

测试:

    @Test
    public void testlogic()
    {
//        Employee employee = new Employee();
//        employee.setId(2);
//        employee.deleteById();
        Employee employee = new Employee();
        employee.setId(2);
        Employee e = employee.selectById();
        System.out.println(e);
    }

以上代码仅仅将deleted置为1,并没有从数据库中删除

3 自动填充 3.1 概述

com.baomidou.mybatisplus.core.handlers.metaObjectHandler

metaObjectHandler接口是MyBatisPlus提供的的一个扩展接口,可以利用这个接口在插入或者更新数据的时候,为一些字段指定默认值。

比如:向数据库插入一条数据的时候,少不了一些向createTime、updateTime此类字段,每次插入的数据都要设置这些个值,十分繁琐,通过实现metaObjectHandler接口重写insertFill、updateFill方法可以自动填写。

本质上 metaObjectHandler获取对象的属性值或者是给对象的属性设置值,最终是要通过Reflector 获取到属性的对应方法的 Invoker, 最终 invoke.

3.2 实现步骤

给tb_employee表添加一列日期型(datetime)数据updatetime

修改Employee类,添加Date型update_Time属性

@Data
//继承Model类 开启AR模式
public class Employee extends Model {

    @TableId(value = "id")
    private Integer id;
    private String empName;
    //指定useremail属性对应的列名为email
    @TableField(value = "email")
    private String useremail;
    private String gender;
    private Integer age;
    @Version
    private Integer version;
    //逻辑删除属性
    @TableLogic
    private Integer deleted;
    //自动填充字段
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updatetime;
    //重写pkVal方法,返回主键
    @Override
    protected Serializable pkVal()
    {
        return this.id;
    }
}

在updateTime上添加 @TableField注解并设置fill参数

//自动填充字段 
@TableField(fill = FieldFill.INSERT_UPDATE) 
private Date updatetime;

填充策略:

创建com.bzcxy.handler包,并实现继承metaObjectHandler接口的类(MymetaObjectHandler),重写insertFill和updateFill方法

public class MymetaObjectHandler implements metaObjectHandler {
    @Override
    public void insertFill(metaObject metaObject) {
        //自动填充逻辑
        
    }

    @Override
    public void updateFill(metaObject metaObject) {
        //自动填充逻辑
       
    }
}

将MymetaObjectHandler类注册到GlobalConfig中

 
    
  
    
        
       
        
    

重写insertFill和updateFill填充逻辑,每次执行update和insert时,都更新当前时间

public class MymetaObjectHandler implements metaObjectHandler {
    @Override
    public void insertFill(metaObject metaObject) {
        //自动填充逻辑
        //通过metaObject来获取需要被填充字段的值 updatetime
        Object fieldvalue = this.getFieldValByName("updatetime",metaObject);
        if (fieldvalue == null)
        {
            //获取当前时间
            Date now = new Date();
            //将当前时间赋值给fieldvalue
            this.setFieldValByName("updatetime",now,metaObject);
        }
    }

    @Override
    public void updateFill(metaObject metaObject) {
        //自动填充逻辑
        //通过metaObject来获取需要被填充字段的值 updatetime
        Object fieldvalue = this.getFieldValByName("updatetime",metaObject);
        if (fieldvalue == null)
        {
            //获取当前时间
            Date now = new Date();
            //将当前时间赋值给fieldvalue
            this.setFieldValByName("updatetime",now,metaObject);
        }
    }
}
4 代码生成器 4.1 概述
  • MP 代码生成器提供了大量的自定义设置,生成的代码完全能够满足各类型的需求

  • MP 的代码生成器 和 Mybatis MBG 代码生成器:
    MP 的代码生成器都是基于 java 代码来生成。MBG 基于 xml 文件进行代码生成

    MBG 的代码生成器可生成: 实体类、Mapper 接口、Mapper 映射文件

    MP 的代码生成器可生成: 实体类(可以选择是否支持 AR)、Mapper 接口、Mapper 映射文件、 Service 层、Controller 层

4.2 使用步骤

MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关
依赖

代码生成器依赖


            com.baomidou
            mybatis-plus-generator
            3.4.1
        

模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,可以选择自己熟悉的模板引擎,

如果不满足要求,可以采用自定义模板引擎。

 
            org.apache.velocity
            velocity-engine-core
            2.2
        

1.全局配置

public class GenratorTest {
    @Test
    public void test()
    {
        //1.全局配置
        GlobalConfig config = new GlobalConfig();
        config.setActiveRecord(true)//是否开启AR模式
              .setAuthor("zhangsihang")//设置作者
              .setOutputDir(System.getProperty("user.dir")+"/src/main/java")//设置输出目录
              .setFileOverride(true)//是否文件覆盖
              .setOpen(false)//生成后是否打开资源管理器(文件夹)
              .setIdType(IdType.AUTO)//主键策略
              .setbaseResultMap(true);//是否生成基本的sql映射文件
	}
}

2.数据源配置

//2.数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL)//设置数据源为mysql
                        .setUrl("jdbc:mysql://localhost:3306/baizhan")//设置url
                        .setDriverName("com.mysql.jdbc.Driver")//设置驱动
                        .setUsername("root")
                        .setPassword("root");

3.策略配置

//3.策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tb_employee")//指定要映射的数据表,可以有多个
                      .setNaming(NamingStrategy.underline_to_camel)// 命名规则下划线转驼峰
                      .setColumnNaming(NamingStrategy.underline_to_camel)//列名规则
                      .setEntityLombokModel(true)//是否生成lombok注解
                      .setTablePrefix("tb_");//设置表名前缀

4.包名配置

//4.包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.bzcxy.generator")//设置根包名
                     .setMapper("mapper")//mapper接口位置
                     .setEntity("pojo")//pojo位置
                     .setController("controller")//控制器位置
                     .setService("service")//service位置
                     .setXml("mapper");//映射文件页在mapper中

5.整合配置

 //5.整合配置
        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(config);
        autoGenerator.setDataSource(dataSourceConfig);
        autoGenerator.setStrategy(strategyConfig);
        autoGenerator.setPackageInfo(packageConfig);
        autoGenerator.execute();

6.执行生成

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;

public class GenratorTest {
    @Test
    public void test()
    {
        //1.全局配置
        GlobalConfig config = new GlobalConfig();
        config.setActiveRecord(true)//是否开启AR模式
              .setAuthor("zhangsihang")//设置作者
              .setOutputDir(System.getProperty("user.dir")+"/src/main/java")//设置输出目录
              .setFileOverride(true)//是否文件覆盖
              .setOpen(false)//生成后是否打开资源管理器(文件夹)
              .setIdType(IdType.AUTO)//主键策略
              .setbaseResultMap(true);//是否生成基本的sql映射文件
        //2.数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL)//设置数据源为mysql
                        .setUrl("jdbc:mysql://localhost:3306/baizhan")//设置url
                        .setDriverName("com.mysql.jdbc.Driver")//设置驱动
                        .setUsername("root")
                        .setPassword("root");
        //3.策略配置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tb_employee")//指定要映射的数据表,可以有多个
                      .setNaming(NamingStrategy.underline_to_camel)// 命名规则下划线转驼峰
                      .setColumnNaming(NamingStrategy.underline_to_camel)//列名规则
                      .setEntityLombokModel(true)//是否生成lombok注解
                      .setTablePrefix("tb_");//设置表名前缀
        //4.包配置
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.bzcxy.generator")//设置根包名
                     .setMapper("mapper")//mapper接口位置
                     .setEntity("pojo")//pojo位置
                     .setController("controller")//控制器位置
                     .setService("service")//service位置
                     .setXml("mapper");//映射文件页在mapper中

        //5.整合配置
        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(config);
        autoGenerator.setDataSource(dataSourceConfig);
        autoGenerator.setStrategy(strategyConfig);
        autoGenerator.setPackageInfo(packageConfig);
        autoGenerator.execute();
    }
}
5 Oracle主键策略

MySQL: 支持主键自增。 IdType.Auto

Oracle: 序列(Sequence)

添加maven依赖


            com.oracle.database.jdbc
            ojdbc8
            19.8.0.0
        
        
            com.oracle.database.nls
            orai18n
            21.1.0.0
        

在db.properties中添加Oracle的连接信息

orcldriver=oracle.jdbc.OracleDriver
orclurl=jdbc:oracle:thin:@localhost:1521:orcl
orclusername=system
orclpassword=root

修改applicationContext.xml数据源为oracle

 
	 
	  
	 
	 
	 

在oracle中新建一个tb_useroracle表

Create table tb_useroracle( 
	id number(11) primary key, 
	name varchar(255) 
);

同时新建一个序列(Sequence)

create sequence seq_useroracle start with 100 increment by 1;

Sequence的常用操作

//查询序列的下一个值 dual代表虚表 
select seq_useroracle.nextval from dual 
//查询序列的当前值 
select seq_useroracle.currval from dual

DBConfig中注册Sequence

 
 
 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 

创建Useroracle实体类并配置主键 Sequence

在类上加@KeySequence注解

给主键配置@TableId(type = IdType.INPUT)

@KeySequence(value=”序列名”)

@Data 
@KeySequence(value = "seq_useroracle") public class Useroracle { 
	@TableId(type = IdType.INPUT) 
	private Integer id; 
	private String name; 
}

创建UseroracleMapper继承baseMapper

public interface UseroracleMapper extends baseMapper { 
}

测试

public class SequenceTest {
    private ApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("applicationContext.xml");
    UseroracleMapper useroracleMapper =
            applicationContext.getBean("useroracleMapper",UseroracleMapper.class);
    @Test
    public void test()
    {
        Useroracle useroracle = new Useroracle();
        useroracle.setName("百战1");
        useroracleMapper.insert(useroracle);
    }
}

向Oracle中插入数据
可以将@keySequence 定义在父类中,可实现多个子类对应的多个表公用一个 Sequence父类

@KeySequence(value = "seq_useroracle") 
public class ParentSequence {
 }

子类继承即可公用Sequence

@Data 
public class Useroracle extends ParentSequence{ 
	@TableId(type = IdType.INPUT) 
	private Integer id; 
	private String name; 
}
6 MyBatisX快速开发插件

MybatisX 辅助 idea 快速开发插件,极高提升开发效率。

可以实现 Java 与 xml 跳转,根据 Mapper 接口中的方法自动生成 xml 结构.

安装MybatisX :

  • 搜索安装
    File -> Settings -> Plugins->Marketplace 输入 MybatisX 安装下载
  • 手动安装
    File -> Settings -> Plugins-> Install plugin from disk 找到MybatisX 安装包进行安装

    注:需要到https://plugins.jetbrains.com/搜索跟自己IDEA对应版本的MybatisX插件安装完成后需要重启IDEA
    给EmployeeMapper编写一个EmployeeMapper.xml
 
 
 

通过Generate statement在EmployeeMapper.xml自动生成xml结构

可以通过(Ctrl+右键+方法名)在xml和接口之间切换
练习源码:https://gitee.com/cutelili/my-batisplus
Git应用与实战

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/444791.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号