美文网首页
Mybatis-plus快速入门与详解

Mybatis-plus快速入门与详解

作者: 背对背拥抱 | 来源:发表于2022-05-18 22:07 被阅读0次

    一、MyBatis-Plus简介

    1、简介

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

    我们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的 1P、2P,基友搭配,效率翻倍。

    image-20220518205901937.png
    2、特性
    • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
    • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
    • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
    • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
    • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
    • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
    • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
    • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
    • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
    • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
    • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
    • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
    3、支持数据库

    任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

    • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
    • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库
    4、框架结构
    image-20220518210026312.png
    5、代码及文档地址

    官方地址: http://mp.baomidou.com

    代码发布地址:

    文档发布地址: https://baomidou.com/pages/24112f

    二、入门案例

    1、建表

    我们使用Mysql8版本

    创建表

    CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
    use `mybatis_plus`;
    CREATE TABLE `user` (
    `id` bigint(20) NOT NULL COMMENT '主键ID',
    `name` varchar(30) DEFAULT NULL COMMENT '姓名',
    `age` int(11) DEFAULT NULL COMMENT '年龄',
    `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    添加数据

    INSERT INTO user (id, name, age, email) VALUES
    (1, 'Jone', 18, 'test1@baomidou.com'),
    (2, 'Jack', 20, 'test2@baomidou.com'),
    (3, 'Tom', 28, 'test3@baomidou.com'),
    (4, 'Sandy', 21, 'test4@baomidou.com'),
    (5, 'Billie', 24, 'test5@baomidou.com');
    
    2、导入依赖
    <dependency>
         <groupId>com.baomidou</groupId>
         <artifactId>mybatis-plus-boot-starter</artifactId>
         <version>3.5.1</version>
    </dependency>
    <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
    </dependency>
    <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <scope>runtime</scope>
    </dependency>
    

    其中,lombok只是为了简化我们实体类的代码

    IDEA 2020.3及以上版本已经内置Lombok plugin了,无需安装插件

    3、application.yml
    spring:
      # 配置数据源信息
      datasource:
      # 配置数据源类型
        type: com.zaxxer.hikari.HikariDataSource
        # 配置连接数据库信息
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
        username: root
        password: root
    
    #配置mybatis日志
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      # 配置MyBatis-Plus操作表的默认前缀
      global-config:
        db-config:
          table-prefix: t_
          # 配置MyBatis-Plus的主键策略
    #      id-type: auto
      # 配置类型别名所对应的包
    #  type-aliases-package: com.zl.po
    
    4、启动类

    在Spring Boot启动类中添加@MapperScan注解,扫描mapper包

    package com.zl;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    
    /**
     * @date 2022-05-15
     * @author ZL
     */
    @SpringBootApplication
    @MapperScan("com.zl.mapper")
    public class MybatisPlusDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MybatisPlusDemoApplication.class, args);
        }
    
    }
    
    5、实体类
    package com.zl.po;
    
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableLogic;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @author zl
     * @time 2022/5/15
     */
    @Data
    @TableName("t_user")
    public class User {
    
        //@TableId("uid")
        private Long id;
    
        //@TableField("user_name")
        private String name;
    
        private Integer age;
    
        private String email;
    
        /**
         * 逻辑删除
         */
        //@TableLogic
       // private Integer isDeleted;
    }
    
    6、通用Mapper接口
    package com.zl.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.zl.po.User;
    import org.springframework.stereotype.Repository;
    
    /**
     * @author zl
     * @time 2022/5/15
     */
    @Repository
    public interface UserMapper extends BaseMapper<User> {
    
    }
    
    7、测试
    package com.zl;
    
    import com.zl.mapper.UserMapper;
    import com.zl.po.User;
    import com.zl.service.UserService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.*;
    
    /**
     * 通用Mapper测试
     */
    @SpringBootTest
    class MybatisPlusTest {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * 查询所有
         * SELECT id,name,age,email FROM user
         */
        @Test
        void testSelectList() {
            List<User> users = userMapper.selectList(null);
            users.forEach(System.out::println);
        }
    }
    

    三、进阶

    1、不同数据库yml配置

    Mysql

    spring:
      # 配置数据源信息
      datasource:
      # 配置数据源类型
        type: com.zaxxer.hikari.HikariDataSource
        # 配置连接数据库信息
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
        username: root
        password: root
    
    #配置mybatis日志
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      # 配置MyBatis-Plus操作表的默认前缀
      global-config:
        db-config:
          table-prefix: t_
          # 配置MyBatis-Plus的主键策略
    #      id-type: auto
      # 配置类型别名所对应的包
    #  type-aliases-package: com.zl.po
    

    其中mysql8的url为:

    jdbc:mysql://localhost:3307/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
    

    mysql5的url为:

    jdbc:mysql://localhost:3307/mybatis_plus?characterEncoding=utf-8&useSSL=false
    

    Sqlserver

    # DataSource Config
    spring:
      datasource:
        username: sa
        password: root
        url: jdbc:sqlserver://localhost:1433;DatabaseName=test
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    

    Oracle

    spring:
      datasource:
        driverClassName: oracle.jdbc.OracleDriver
        username: root
        password: root
        url: jdbc:oracle:thin:@//localhost:1521/test
    
    2、通用Service接口

    Uservice

    package com.zl.service;
    
    import com.baomidou.mybatisplus.extension.service.IService;
    import com.zl.po.User;
    
    /**
     * @author zl
     * @time 2022/5/15
     */
    public interface UserService extends IService<User> {
    }
    

    UserServiceImpl

    package com.zl.service.impl;
    
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.zl.mapper.UserMapper;
    import com.zl.po.User;
    import com.zl.service.UserService;
    import org.springframework.stereotype.Service;
    
    /**
     * @author zl
     * @time 2022/5/15
     */
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    }
    
    3、通用Mapper和通用Service常规用法
    package com.zl;
    
    import com.zl.mapper.UserMapper;
    import com.zl.po.User;
    import com.zl.service.UserService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.*;
    
    /**
     * 通用Mapper测试
     */
    @SpringBootTest
    class MybatisPlusTest {
    
        @Autowired
        private UserMapper userMapper;
    
        @Autowired
        private UserService userService;
    
        
        /**
         * 查询所有
         * SELECT id,name,age,email FROM user
         */
        @Test
        void testSelectList() {
            List<User> users = userMapper.selectList(null);
            users.forEach(System.out::println);
        }
    
        /**
         * 插入
         * INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
         */
        @Test
        void testInsert(){
            User user = new User();
            user.setName("张三");
            user.setAge(23);
            user.setEmail("zhangsan@163.com");
            int result = userMapper.insert(user);
            System.out.println("受影响的行数:"+result);
            System.out.println("新建的ID:"+user.getId());
        }
    
        /**
         * 根据ID删除
         * DELETE FROM user WHERE id=?
         */
        @Test
        void testDeleteById(){
            int result = userMapper.deleteById(1525835539440345090L);
            System.out.println("受影响的行数:"+result);
        }
    
    
        /**
         * 根据ID批量删除
         * DELETE FROM user WHERE id IN ( ? , ? )
         */
        @Test
        void testDeleteBatchIds(){
            int result = userMapper.deleteBatchIds(Arrays.asList(1L, 2L));
            System.out.println("受影响的行数:"+result);
        }
    
    
        /**
         * 根据Map删除
         * DELETE FROM user WHERE name = ? AND age = ?
         */
        @Test
        void testDeleteByMap(){
            Map<String,Object> map = new HashMap<>();
            map.put("age",21);
            map.put("name","Sandy");
            int result = userMapper.deleteByMap(map);
            System.out.println("受影响的行数:"+result);
        }
    
    
        /**
         * 根据ID更新
         * UPDATE user SET name=?, age=? WHERE id=?
         */
        @Test
        void testUpdateById(){
            User user = new User();
            user.setId(5L);
            user.setName("admin");
            user.setAge(33);
    
            int result = userMapper.updateById(user);
            System.out.println("受影响的行数:"+result);
        }
    
    
        /**
         * 根据ID查询
         * SELECT id,name,age,email FROM user WHERE id=?
         */
        @Test
        void testSelectById(){
            User user = userMapper.selectById(5L);
            System.out.println(user);
        }
    
    
        /**
         * 根据ID批量查询
         * SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
         */
        @Test
        void testSelectByBatchIds(){
            List<User> users = userMapper.selectBatchIds(Arrays.asList(3L, 5L));
            users.forEach(System.out::println);
        }
    
    
        /**
         * 根据Map查询
         * SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
         */
        @Test
        void testSelectByMap(){
            Map<String,Object> map = new HashMap<>();
            map.put("name","admin");
            map.put("age",33);
            List<User> users = userMapper.selectByMap(map);
            users.forEach(System.out::println);
        }
    
        /**
         * 查询总记录数
         * SELECT COUNT( * ) FROM user
         */
        @Test
        void testGetCount(){
            long count = userService.count();
            System.out.println("总记录数:"+count);
        }
    
    
        /**
         * 批量插入:执行10次
         * INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
         */
        @Test
        void testSaveBatch(){
            List<User> userList = new ArrayList<>();
            for (int i=0;i<10;i++){
                User user = new User();
                user.setName("zl" + i);
                user.setAge(20 + i);
                userList.add(user);
            }
    
            boolean flag = userService.saveBatch(userList);
            System.out.println("插入是否成功:"+flag);
        }
    }
    
    4、Wrapper常规用法
    package com.zl;
    
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
    import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
    import com.baomidou.mybatisplus.core.toolkit.StringUtils;
    import com.zl.mapper.UserMapper;
    import com.zl.po.User;
    import com.zl.service.UserService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Wrapper测试
     * @author zl
     * @time 2022/5/15
     */
    @SpringBootTest
    public class MybatisPlusWrapperTest {
    
        @Autowired
        private UserMapper userMapper;
    
        @Autowired
        private UserService userService;
    
    
        /**
         * 查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息
         * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
         */
        @Test
        void test01(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("user_name","a")
                    .between("age",20,30)
                    .isNotNull("email");
            List<User> userList = userMapper.selectList(queryWrapper);
            userList.forEach(System.out::println);
        }
    
    
        /**
         * 按年龄降序查询用户,如果年龄相同则按id升序排列
         * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,uid ASC
         */
        @Test
        void test02(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByDesc("age").orderByAsc("uid");
            List<User> userList = userMapper.selectList(queryWrapper);
            userList.forEach(System.out::println);
        }
    
    
        /**
         * 删除email为空的用户
         * UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)
         */
        @Test
        void test03(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.isNull("email");
            int result = userMapper.delete(queryWrapper);
            System.out.println("影响的行数:"+result);
        }
    
    
        /**
         * 将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
         * UPDATE t_user SET age=?, email=? WHERE is_deleted=0 AND (age >= ? AND user_name LIKE ? OR email IS NULL)
         */
        @Test
        void test04(){
            User user = new User();
            user.setAge(10);
            user.setEmail("zl@163.com");
    
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.ge("age",20)
                    .like("user_name","a")
                    .or()
                    .isNull("email");
    
            int result = userMapper.update(user, queryWrapper);
            System.out.println("受影响的行数:"+result);
        }
    
    
        /**
         * 将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
         * UPDATE t_user SET age=?, email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age >= ? OR email IS NULL))
         */
        @Test
        void test05(){
            User user = new User();
            user.setAge(15);
            user.setEmail("zl2@163.com");
    
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("user_name","a")
                    .and(i->i.ge("age",20).or().isNull("email"));
    
            int result = userMapper.update(user, queryWrapper);
            System.out.println("受影响的行数:"+result);
        }
    
        //todo 组装select子句
    
    
        /**
         * 查询用户信息的username和age字段
         * SELECT user_name,age FROM t_user WHERE is_deleted=0
         */
        @Test
        void test06(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("user_name","age");
    
            //selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为null
            List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
            maps.forEach(System.out::println);
        }
    
    
        /**
         * 将(年龄大于20或邮箱为null)并且用户名中包含有a的用户信息修改
         * UPDATE t_user SET age=?,email=? WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))
         */
        @Test
        void test07(){
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("age",18)
                    .set("email","zl@163.com")
                    .like("user_name","a")
                    .and(i->i.gt("age",20).or().isNull("email"));
    
            int result = userMapper.update(null, updateWrapper);
            System.out.println("影响行数:"+result);
        }
    
    
        /**
         * Condition条件
         * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (age >= ? AND age <= ?)
         */
        @Test
        void test08(){
            //定义查询条件,有可能为null(用户未输入或未选择)
            String username = null;
            Integer ageBegin = 10;
            Integer ageEnd = 24;
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.like(StringUtils.isNotBlank(username), "username", "a")
                    .ge(ageBegin != null, "age", ageBegin)
                    .le(ageEnd != null, "age", ageEnd);
    
            List<User> userList = userMapper.selectList(queryWrapper);
            userList.forEach(System.out::println);
        }
    
    
    
        @Test
        public void test09() {
            //定义查询条件,有可能为null(用户未输入)
            String username = "a";
            Integer ageBegin = 10;
            Integer ageEnd = 24;
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            //避免使用字符串表示字段,防止运行时错误
            queryWrapper
                    .like(StringUtils.isNotBlank(username), User::getName, username)
                    .ge(ageBegin != null, User::getAge, ageBegin)
                    .le(ageEnd != null, User::getAge, ageEnd);
            List<User> users = userMapper.selectList(queryWrapper);
            users.forEach(System.out::println);
        }
    
    
    
        @Test
        public void test10() {
            //组装set子句
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper
                    .set(User::getAge, 18)
                    .set(User::getEmail, "user@atguigu.com")
                    .like(User::getName, "a")
                    .and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail));
            //lambda表达式内的逻辑优先运算
            User user = new User();
            int result = userMapper.update(user, updateWrapper);
            System.out.println("受影响的行数:" + result);
        }
    }
    
    5、分页和乐观锁
    1) 分页

    配置类-包含分页和乐观锁

    package com.zl.config;
    
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * 插件配置类-包含分页插件、乐观锁
     * @author zl
     * @time 2022/5/16
     */
    @Configuration
    public class MybatisPlusConfig {
    
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            //添加分页插件
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            //添加乐观锁插件
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
    }
    

    简单测试--查询所有

    /**
         * 分页
         * SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 LIMIT ?,?
         */
        @Test
        void testPage(){
            //当前页、每页显示条数
            Page<User> page = new Page<>(1,2);
            userMapper.selectPage(page, null);
    
            //获取分页数据
            List<User> list = page.getRecords();
            list.forEach(System.out::println);
            System.out.println("当前页:"+page.getCurrent());
            System.out.println("每页显示的条数:"+page.getSize());
            System.out.println("总记录数:"+page.getTotal());
            System.out.println("总页数:"+page.getPages());
            System.out.println("是否有上一页:"+page.hasPrevious());
            System.out.println("是否有下一页:"+page.hasNext());
        }
    

    自定义分页接口

    Mapper

    /**
    * 根据年龄查询用户列表,分页显示
    * @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位
    * @param age 年龄
    * @return
    */
    Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
    

    UserMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.zl.mapper.UserMapper">
    
        <!--  当实体类的属性名称和数据库的列名不一致时,需要用resultMap映射   -->
        <resultMap id="UserMap" type="User">
            <!-- id为主键 -->
            <id column="id" property="id"/>
            <!-- column是数据库表的列名 , property是对应实体类的属性名 -->
            <result column="uid" property="id"/>
            <result column="user_name" property="name"/>
        </resultMap>
    
        <!--Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
        <select id="selectPageVo" resultMap="UserMap">
            select uid,user_name,age,email from t_user where age > #{age}
        </select>
    
    </mapper>
    

    测试类

        /**
         *
         * 自定义分页接口
         */
        @Test
        public void testSelectPageVo(){
            //设置分页参数
            Page<User> page = new Page<>(1, 2);
            userMapper.selectPageVo(page, 10);
            //获取分页数据
            List<User> list = page.getRecords();
            list.forEach(System.out::println);
            System.out.println("当前页:"+page.getCurrent());
            System.out.println("每页显示的条数:"+page.getSize());
            System.out.println("总记录数:"+page.getTotal());
            System.out.println("总页数:"+page.getPages());
            System.out.println("是否有上一页:"+page.hasPrevious());
            System.out.println("是否有下一页:"+page.hasNext());
        }
    
    2) 乐观锁

    数据库表要增加一个字段version

    然后用注解@Version

    package com.zl.po;
    
    import com.baomidou.mybatisplus.annotation.Version;
    import lombok.Data;
    
    /**
     * @author zl
     * @time 2022/5/16
     */
    @Data
    public class Product {
    
        private Long id;
        private String name;
        private Integer price;
    
        @Version
        private Integer version;
    }
    

    测试代码

    /**
     * 乐观锁
     */
    @Test
    public void testProduct01(){
        //小李查询商品价格
        Product productLi = productMapper.selectById(1);
        System.out.println("小李查询的商品价格:"+productLi.getPrice());
        //小王查询商品价格
        Product productWang = productMapper.selectById(1);
        System.out.println("小王查询的商品价格:"+productWang.getPrice());
        //小李将商品价格+50
        productLi.setPrice(productLi.getPrice()+50);
        productMapper.updateById(productLi);
        //小王将商品价格-30
        productWang.setPrice(productWang.getPrice()-30);
        int result = productMapper.updateById(productWang);
        if(result == 0){
            //操作失败,重试
            Product productNew = productMapper.selectById(1);
            productNew.setPrice(productNew.getPrice()-30);
            productMapper.updateById(productNew);
        }
        //老板查询商品价格
        Product productLaoban = productMapper.selectById(1);
        System.out.println("老板查询的商品价格:"+productLaoban.getPrice());
    }
    
    6、代码生成器

    依赖

    <!--   代码生成器  -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.31</version>
    </dependency>
    

    测试类

    package com.zl;
    
    import com.baomidou.mybatisplus.generator.FastAutoGenerator;
    import com.baomidou.mybatisplus.generator.config.OutputFile;
    import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
    import java.util.Collections;
    
    /**
     * @author zl
     * @time 2022/5/16
     */
    public class FastAutoGeneratorTest {
    
        public static void main(String[] args) {
            FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3307/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "root")
                    .globalConfig(builder -> {
                        builder.author("zl") // 设置作者
                                //.enableSwagger() // 开启 swagger 模式
                                .fileOverride() // 覆盖已生成文件
                                .outputDir("D://mybatis_plus"); // 指定输出目录
                    })
                    .packageConfig(builder -> {
                        builder.parent("com.zl") // 设置父包名
                                .moduleName("mybatisplus") // 设置父包模块名
                                .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus")); // 设置mapperXml生成路径
                    })
                    .strategyConfig(builder -> {
                        builder.addInclude("t_user") // 设置需要生成的表名
                                .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                    })
                    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                    .execute();
        }
    }
    
    7、多数据源

    依赖

    <!--   多数据源  -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>3.5.0</version>
    </dependency>
    

    配置文件

    spring:
      # 配置数据源信息
      datasource:
        dynamic:
          # 设置默认的数据源或者数据源组,默认值即为master
          primary: master
          # 严格匹配数据源,默认false.true未匹配到指定数据源时抛异常,false使用默认数据源
          strict: false
          datasource:
            master:
              url: jdbc:mysql://localhost:3307/mybatis_plus?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
              driver-class-name: com.mysql.cj.jdbc.Driver
              username: root
              password: root
            slave_1:
              url: jdbc:mysql://localhost:3307/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
              driver-class-name: com.mysql.cj.jdbc.Driver
              username: root
              password: root
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      type-aliases-package: com.zl.po
    

    在UserServiceImpl上加上注解@DS

    package com.zl.service.impl;
    
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.zl.mapper.UserMapper;
    import com.zl.po.User;
    import com.zl.service.UserService;
    import org.springframework.stereotype.Service;
    
    /**
     * @author zl
     * @time 2022/5/15
     */
    //指定所操作的数据源
    @DS("master") 
    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    }
    
    8、MybatisX插件

    MyBatis-Plus为我们提供了强大的mapper和service模板,能够大大的提高开发效率

    但是在真正开发过程中,MyBatis-Plus并不能为我们解决所有问题,例如一些复杂的SQL,多表 联查,我们就需要自己去编写代码和SQL语句,我们该如何快速的解决这个问题呢,这个时候可 以使用MyBatisX插件 MyBatisX一款基于 IDEA 的快速开发插件,为效率而生。

    MyBatisX插件用法:https://baomidou.com/pages/ba5b24

    相关文章

      网友评论

          本文标题:Mybatis-plus快速入门与详解

          本文链接:https://www.haomeiwen.com/subject/ughzurtx.html