详细解析MyBatis Plus框架的核心功能!MyBatis Plus框架经典使用场景的分析说明

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 本篇文章介绍了MyBatis Plus框架的核心功能,使用代码实例介绍了MyBatis Plus框架集成SpringBoot和Spring框架的具体使用。最后对MyBatis Plus框架的几个经典场景的使用进行具体的分析与说明,包括代码生成器,通用CRUD,条件构造器,自定义SQL语句,分页插件和性能分析插件,公共字段自动插入。通过这篇文章,可以对MyBatis Plus框架有更全面的认识。

ORM框架-Mybatis Plus

MyBatis Plus是在 MyBatis 的基础上只做增强不做改变,可以简化开发,提高效率.

Mybatis Plus核心功能

  • 支持通用的 CRUD,代码生成器与条件构造器
  • 通用CRUD: 定义好Mapper接口后,只需要继承 BaseMapper接口即可获得通用的增删改查功能,无需编写任何接口方法与配置文件
  • 条件构造器: 通过EntityWrapper(实体包装类),可以用于拼接SQL语句,并且支持排序,分组查询等复杂的 SQL
  • 代码生成器: 支持一系列的策略配置与全局配置,比 MyBatis 的代码生成更好用

BaseMapper接口中通用的 CRUD 方法:
在这里插入图片描述

MyBatis Plus与SpringBoot集成

  • 数据库USER
DROP TABLE IF EXISTS user;
CREATE TABLE user(
  id bigint(20) DEFAULT NULL COMMENT '唯一标示',
  code varchar(20) DEFAULT NULL COMMENT '编码',
  name varchar(64) DEFAULT NULL COMMENT '名称',
  status char(1) DEFAULT 1 COMMENT '状态 1启用 0 停用',
  gmt_create datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  gmt_modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • pom.xml依赖
 <!--mybatis plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatisplus-spring-boot-starter</artifactId>
    <version>1.0.5</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>2.1.9</version>
</dependency>
  • spring-mybatis.xml配置文件

也可以直接使用@Bean的方式进行或者通过application配置文件进行

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans%20http://www.springframework.org/schema/beans/spring-beans.xsd%20http://www.springframework.org/schema/tx%20http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--创建jdbc数据源 这里直接使用阿里的druid数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="${mysql.driver}"/>
        <property name="url" value="${mysql.url}"/>
        <property name="username" value="${mysql.username}"/>
        <property name="password" value="${mysql.password}"/>
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="0"/>
        <!-- 连接池最大使用连接数量 -->
        <property name="maxActive" value="20"/>
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="20"/>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="0"/>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="60000"/>

        <property name="validationQuery" value="${validationQuery}"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
        <property name="testWhileIdle" value="true"/>

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000"/>

        <!-- 打开removeAbandoned功能 -->
        <property name="removeAbandoned" value="true"/>
        <!-- 1800秒,也就是30分钟 -->
        <property name="removeAbandonedTimeout" value="1800"/>
        <!-- 关闭abanded连接时输出错误日志 -->
        <property name="logAbandoned" value="true"/>

        <!-- 监控数据库 -->
        <property name="filters" value="mergeStat"/>
    </bean>

    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 可通过注解控制事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--mybatis-->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 自动扫描mapper.xml文件,支持通配符 -->
        <property name="mapperLocations" value="classpath:mapper/**/*.xml"/>
        <!-- 配置文件,比如参数配置(是否启动驼峰等)、插件配置等 -->
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <!-- 启用别名,这样就无需写全路径类名了,具体可自行查阅资料 -->
        <property name="typeAliasesPackage" value="cn.lqdev.learning.springboot.chapter9.biz.entity"/>
        <!-- MP 全局配置注入 -->
        <property name="globalConfig" ref="globalConfig"/>
    </bean>
    <bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
        <!--
            AUTO->`0`("数据库ID自增")QW
             INPUT->`1`(用户输入ID")
            ID_WORKER->`2`("全局唯一ID")
            UUID->`3`("全局唯一ID")
        -->
        <property name="idType" value="3" />
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 自动扫描包路径,接口自动注册为一个bean类 -->
        <property name="basePackage" value="cn.lqdev.learning.springboot.chapter9.biz.dao"/>
    </bean>

</beans>
  • 编写启动类,应用启动时自动加载配置xml文件
@Configuration
@ImportResource(locations = {"classpath:/mybatis/spring-mybatis.xml"})
//@MapperScan("cn.lqdev.learning.springboot.chapter9.biz.dao")
//@EnableTransactionManagement
public class MybatisPlusConfig {
}

MyBatis Plus集成Spring

  • 数据表结构
DROP TABLE IF EXISTS tbl_employee;
CREATE TABLE tbl_employee(
  id int(11) NOT NULL AUTO_INCREMENT,
  last_name varchar(50) DEFAULT NULL,
  email varchar(50) DEFAULT NULL,
  gender char(1) DEFAULT NULL,
  age int(11) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
  • pom.xml
    <dependencies>
        <!-- MP -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>2.3</version>
        </dependency>
        <!-- 测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
        </dependency>
        <!-- Spring 相关 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.3.9.RELEASE</version>
        </dependency>
    </dependencies>
  • MyBatis全局配置文件mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 不作任何配置 -->
<configuration />
  • 数据源db.properties
jdbc.url=jdbc:mysql://localhost:3306/mp
jdbc.username=mp
jdbc.password=mp
  • Spring 配置文件applicationContext.xml
    <!-- 数据源 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- MP 提供的 MybatisSqlSessionFactoryBean -->
    <bean id="sqlSessionFactoryBean" 
          class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- mybatis 全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <!-- 别名处理 -->
        <property name="typeAliasesPackage" value="com.jas.bean"></property>
        <!-- 注入全局MP策略配置 -->
        <property name="globalConfig" ref="globalConfiguration"></property>
        <!-- 插件注册 -->
        <property name="plugins">
            <list>
                <!-- 注册分页插件 -->
                <bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor" />
                <!-- 注入 SQL 性能分析插件,建议在开发环境中使用,可以在控制台查看 SQL 执行日志 -->
                <bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
                    <property name="maxTime" value="1000" />
                    <!--SQL 是否格式化 默认false-->
                    <property name="format" value="true" />
                </bean>
            </list>
        </property>
    </bean>

    <!-- 定义 MybatisPlus 的全局策略配置-->
    <bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
        <!-- 在 2.3 版本以后,dbColumnUnderline 默认值是 true -->
        <property name="dbColumnUnderline" value="true"></property>
        <!-- 全局的主键策略 -->
        <property name="idType" value="0"></property>
        <!-- 全局的表前缀策略配置 -->
        <property name="tablePrefix" value="tbl_"></property>
    </bean>
    
    <!-- 配置mybatis 扫描mapper接口的路径 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.jas.mapper"></property>
    </bean>

MyBatis Plus使用示例

  • 实体类Employee
@TableName(value = "tbl_employee")
public class Employee {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @TableField(value = "last_name")
    private String lastName;
    private String email;
    private Integer gender;
    private Integer age;

    public Employee() {
        super();
    }
    
    public Employee(Integer id, String lastName, String email, Integer gender, Integer age) {
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
        this.age = age;
    }
    // 省略 set、get 与 toString() 方法
  • mapper接口
/**
* 不定义任何接口方法
*/
public interface EmployeeMapper extends BaseMapper<Employee> {}
  • 在测试类中生成测试的mapper对象
    private ApplicationContext context = 
            new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
            
    private EmployeeMapper employeeMapper = 
            context.getBean("employeeMapper", EmployeeMapper.class);
  • 查询:
    @Test
    public void getEmpByIdTest() {
        Employee employee = employeeMapper.selectById(1);
        
        System.out.println(employee);
    }
  • 分页查询:
    @Test
    public void getEmpByPage() {
        Page<?> page = new Page<>(1, 5);
        List<Employee> list = employeeMapper.selectPage(page, null);
        
        System.out.println("总记录数:" + page.getTotal());
        System.out.println("总页数" + page.getPages());
        System.out.println(list);
    }
  • 条件构造器:
    @Test
    public void getEmpByName() {
        EntityWrapper<Employee> wrapper = new EntityWrapper<>();
        
        // 'last_name' 与 'age' 对应数据库中的字段 
        wrapper.like("last_name", "张");
        wrapper.eq("age", 20);
        
        List<Employee> list = employeeMapper.selectList(wrapper);
        System.out.println(list);
    }

控制台输出的SQL分析日志
在这里插入图片描述
简单的数据库操作不需要在 EmployeeMapper 接口中定义任何方法,也没有在配置文件中编写SQL语句,而是通过继承BaseMapper接口获得通用的的增删改查方法,复杂的SQL也可以使用条件构造器拼接.不过复杂的业务需求还是要编写SQL语句的,流程和MyBatis一样.

MyBatis Plus使用场景

代码生成器
  • 代码生成器依赖velocity模版引擎,引入依赖
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
    <scope>test</scope>
</dependency>
  • 代码生成器类MysqlGenerator:
public class MysqlGenerator {

    private static final String PACKAGE_NAME = "cn.lqdev.learning.springboot.chapter9";
    private static final String MODULE_NAME = "biz";
    private static final String OUT_PATH = "D:\\develop\\code";
    private static final String AUTHOR = "oKong";

    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/learning?useUnicode=true&characterEncoding=UTF-8";
    private static final String USER_NAME = "root";
    private static final String PASSWORD = "123456";

    /**
     * <p>
     * MySQL 生成演示
     * </p>
     */
    public static void main(String[] args) {
        // 自定义需要填充的字段
        List<TableFill> tableFillList = new ArrayList<TableFill>();

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator().setGlobalConfig(
                // 全局配置
                new GlobalConfig().setOutputDir(OUT_PATH)// 输出目录
                        .setFileOverride(true)// 是否覆盖文件
                        .setActiveRecord(true)// 开启 activeRecord 模式
                        .setEnableCache(false)// XML 二级缓存
                        .setBaseResultMap(false)// XML ResultMap
                        .setBaseColumnList(true)// XML columList
                        .setAuthor(AUTHOR)
                        // 自定义文件命名,注意 %s 会自动填充表实体属性!
                        .setXmlName("%sMapper").setMapperName("%sDao")
        // .setServiceName("MP%sService")
        // .setServiceImplName("%sServiceDiy")
        // .setControllerName("%sAction")
        ).setDataSource(
                // 数据源配置
                new DataSourceConfig().setDbType(DbType.MYSQL)// 数据库类型
                        .setTypeConvert(new MySqlTypeConvert() {
                            // 自定义数据库表字段类型转换【可选】
                            @Override
                            public DbColumnType processTypeConvert(String fieldType) {
                                System.out.println("转换类型:" + fieldType);
                                // if ( fieldType.toLowerCase().contains( "tinyint" ) ) {
                                // return DbColumnType.BOOLEAN;
                                // }
                                return super.processTypeConvert(fieldType);
                            }
                        }).setDriverName(DRIVER).setUsername(USER_NAME).setPassword(PASSWORD).setUrl(URL))
                .setStrategy(
                        // 策略配置
                        new StrategyConfig()
                                // .setCapitalMode(true)// 全局大写命名
                                .setDbColumnUnderline(true)// 全局下划线命名
                                // .setTablePrefix(new String[]{"unionpay_"})// 此处可以修改为您的表前缀
                                .setNaming(NamingStrategy.underline_to_camel)// 表名生成策略
                                // .setInclude(new String[] {"citycode_org"}) // 需要生成的表
                                // .setExclude(new String[]{"test"}) // 排除生成的表
                                // 自定义实体,公共字段
                                // .setSuperEntityColumns(new String[]{"test_id"})
                                .setTableFillList(tableFillList)
                                // 自定义实体父类
                                // .setSuperEntityClass("com.baomidou.demo.common.base.BsBaseEntity")
                                // // 自定义 mapper 父类
                                // .setSuperMapperClass("com.baomidou.demo.common.base.BsBaseMapper")
                                // // 自定义 service 父类
                                // .setSuperServiceClass("com.baomidou.demo.common.base.BsBaseService")
                                // // 自定义 service 实现类父类
                                // .setSuperServiceImplClass("com.baomidou.demo.common.base.BsBaseServiceImpl")
                                // 自定义 controller 父类
                                // .setSuperControllerClass("com.baomidou.demo.TestController")
                                // 【实体】是否生成字段常量(默认 false)
                                // public static final String ID = "test_id";
                                .setEntityColumnConstant(true)
                                // 【实体】是否为构建者模型(默认 false)
                                // public User setName(String name) {this.name = name; return this;}
                                .setEntityBuilderModel(true)
                                // 【实体】是否为lombok模型(默认 false)<a href="https://projectlombok.org/">document</a>
                                .setEntityLombokModel(true)
                // Boolean类型字段是否移除is前缀处理
                // .setEntityBooleanColumnRemoveIsPrefix(true)
                // .setRestControllerStyle(true)
                // .setControllerMappingHyphenStyle(true)
                ).setPackageInfo(
                        // 包配置
                        new PackageConfig().setModuleName(MODULE_NAME).setParent(PACKAGE_NAME)// 自定义包路径
                                .setController("controller")// 这里是控制器包名,默认 web
                                .setXml("mapper").setMapper("dao")

                ).setCfg(
                        // 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值
                        new InjectionConfig() {
                            @Override
                            public void initMap() {
                                Map<String, Object> map = new HashMap<String, Object>();
                                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                                this.setMap(map);
                            }
                        }.setFileOutConfigList(
                                Collections.<FileOutConfig>singletonList(new FileOutConfig("/templates/mapper.xml.vm") {
                                    // 自定义输出文件目录
                                    @Override
                                    public String outputFile(TableInfo tableInfo) {
                                        return OUT_PATH + "/xml/" + tableInfo.getEntityName() + "Mapper.xml";
                                    }
                                })))
                .setTemplate(
                        // 关闭默认 xml 生成,调整生成 至 根目录
                        new TemplateConfig().setXml(null)
        // 自定义模板配置,模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy
        // 至您项目 src/main/resources/template 目录下,模板名称也可自定义如下配置:
        // .setController("...");
        // .setEntity("...");
        // .setMapper("...");
        // .setXml("...");
        // .setService("...");
        // .setServiceImpl("...");
        );

        // 执行生成
        mpg.execute();
    }

}
通用CRUD
  • 通用CRUD测试类GeneralTest:
@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest 
@Slf4j
public class GeneralTest {

    @Autowired
    IUserService userService;

    @Test
    public void testInsert() {
        User user = new User();
        user.setCode("001");
        user.setName("okong-insert");
        //默认的插入策略为:FieldStrategy.NOT_NULL,即:判断 null
        //对应在mapper.xml时写法为:<if test="field!=null">
        //这个可以修改的,设置字段的@TableField(strategy=FieldStrategy.NOT_EMPTY)
        //所以这个时候,为null的字段是不会更新的,也可以开启性能插件,查看sql语句就可以知道
        userService.insert(user);

        //新增所有字段,
        userService.insertAllColumn(user);
        log.info("新增结束");
    }

    @Test
    public void testUpdate() {

        User user = new User();
        user.setCode("101");
        user.setName("oKong-insert");
        //这就是ActiveRecord的功能
        user.insert();
        //也可以直接 userService.insert(user);

        //更新
        User updUser = new User();
        updUser.setId(user.getId());
        updUser.setName("okong-upd");

        updUser.updateById();
        log.info("更新结束");
    }

    @Test
    public void testDelete() {
        User user = new User();
        user.setCode("101");
        user.setName("oKong-delete");

        user.insert();

        //删除
        user.deleteById();
        log.info("删除结束");

    }

    @Test
    public void testSelect() {
        User user = new User();
        user.setCode("201");
        user.setName("oKong-selecdt");

        user.insert();

        log.info("查询:{}",user.selectById());
    }
}
  • MyBatis Plus定义的数据库操作方法

在这里插入图片描述
对于通用代码如何注入的,可查看com.baomidou.mybatisplus.mapper.AutoSqlInjector类,这个就是注入通用的CURD方法的类.

条件构造器

条件构造器主要提供了实体包装器,用于处理SQL语句拼接,排序,实体参数查询:使用的是数据库字段,不是Java属性

  • sql条件拼接:

SQL条件拼接测试类ConditionTest

@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest 
@Slf4j
public class ConditionTest {

    @Autowired
    IUserService userService;

    @Test
    public void testOne() {
        User user =  new User();
        user.setCode("701");
        user.setName("okong-condition");
        user.insert();

        EntityWrapper<User> qryWrapper = new EntityWrapper<>();

        qryWrapper.eq(User.CODE, user.getCode());
        qryWrapper.eq(User.NAME, user.getName());

        //也可以直接 
//        qryWrapper.setEntity(user);

        //打印sql语句
        System.out.println(qryWrapper.getSqlSegment());

        //设置select 字段 即:select code,name from 
        qryWrapper.setSqlSelect(User.CODE,User.NAME);
        System.out.println(qryWrapper.getSqlSelect());

        //查询
        User qryUser = userService.selectOne(qryWrapper);
        System.out.println(qryUser);
        log.info("拼接一结束");
    }

    @Test
    public void testTwo() {
        User user =  new User();
        user.setCode("702");
        user.setName("okong-condition");
        user.insert();

        EntityWrapper<User> qryWrapper = new EntityWrapper<>();
        qryWrapper.where("code = {0}", user.getCode())
        .and("name = {0}",user.getName())
        .andNew("status = 0");
        System.out.println(qryWrapper.getSqlSegment());
        //等等很复杂的。
        //复杂的建议直接写在xml里面了,要是非动态的话 比较xml一眼看得懂呀
        //查询
        User qryUser = userService.selectOne(qryWrapper);
        System.out.println(qryUser);
        log.info("拼接二结束");
    }

}

MyBatis Plus提供的条件构造方法com.baomidou.mybatisplus.mapper.Wrapper
在这里插入图片描述

  • 自定义SQL使用条件构造器:

UserDao.java加入接口方法:

/**
     * 
     * @param rowBounds 分页对象 直接传入page即可
     * @param wrapper 条件构造器
     * @return
     */
    List<User> selectUserWrapper(RowBounds rowBounds, @Param("ew") Wrapper<User> wrapper);

UserMapper.xml加入对应的xml节点:

    <!-- 条件构造器形式 -->
    <select id="selectUserWrapper" resultType="user">
        SELECT
        <include refid="Base_Column_List" />
        FROM USER
        <where>
            ${ew.sqlSegment}
        </where>
    </select>

自定义SQL使用条件构造器测试类:

@Test
    public void testCustomSql() {
        User user = new User();
        user.setCode("703");
        user.setName("okong-condition");
        user.insert();

        EntityWrapper<User> qryWrapper = new EntityWrapper<>();
        qryWrapper.eq(User.CODE, user.getCode());

        Page<User> pageUser = new Page<>();
        pageUser.setCurrent(1);
        pageUser.setSize(10);

        List<User> userlist = userDao.selectUserWrapper(pageUser, qryWrapper);
        System.out.println(userlist.get(0));
        log.info("自定义sql结束");
    }
  • xml形式使用wrapper:

UserDao.java:

/**
     * 
     * @param rowBounds 分页对象 直接传入page即可
     * @param wrapper 条件构造器
     * @return
     */
    List<User> selectUserWrapper(RowBounds rowBounds, @Param("ew") Wrapper<User> wrapper);

UserMapper.xml:


    <!-- 条件构造器形式 -->
    <select id="selectUserWrapper" resultType="user">
        SELECT
        <include refid="Base_Column_List" />
        FROM USER
        <where>
            ${ew.sqlSegment}
        </where>
    </select>
  • 条件参数说明:
查询方式 使用说明
setSqlSelect 设置SELECT查询字段
where WHERE语句,拼接+WHERE条件
and AND语句,拼接+AND 字段=值
andNew AND 语句,拼接+AND(字段=值)
or OR 语句,拼接+OR 字段=值
orNew OR 语句,拼接+OR(字段=值)
eq 等于=
allEq 基于map内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
like 模糊查询 LIKE
notLike 模糊查询NOT LIKE
in IN 查询
notIn NOT IN查询
isNull NULL值查询
isNotNull IS NOT NULL
groupBy 分组GROUP BY
having HAVING关键词
orderBy 排序ORDER BY
orderAsc 排序ASC ORDER BY
orderDesc 排序DESC ORDER BY
exists EXISTS条件语句
notExists NOT EXISTS条件语句
between BETWEEN条件语句
notBetween NOT BETWEEN条件语句
addFilter 自由拼接SQL
last 拼接在最后
自定义SQL语句

在多表关联时,条件构造器和通用CURD都无法满足时,可以编写SQL语句进行扩展.这些都是mybatis的用法.首先改造UserDao接口,有两种方式:

  • 注解形式:
@Select("SELECT * FROM USER WHERE CODE = #{userCode}")
    List<User> selectUserCustomParamsByAnno(@Param("userCode")String userCode);
  • xml形式:
List<User> selectUserCustomParamsByXml(@Param("userCode")String userCode);

UserMapper.xml新增一个节点:

    <!-- 由于设置了别名:typeAliasesPackage=cn.lqdev.learning.mybatisplus.samples.biz.entity,所以resultType可以不写全路径了。 -->
    <select id="selectUserCustomParamsByXml" resultType="user">
        SELECT 
        <include refid="Base_Column_List"/> 
        FROM USER 
       WHERE CODE = #{userCode}
    </select>

自定义SQL语句测试类CustomSqlTest:

@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest 
@Slf4j
public class CustomSqlTest {

    @Autowired
    UserDao userDao;

    @Test
    public void testCustomAnno() {
        User user = new User();
        user.setCode("901");
        user.setName("okong-sql");
        user.insert();
        List<User> userlist = userDao.selectUserCustomParamsByAnno(user.getCode());
        //由于新增的 肯定不为null 故不判断了。
        System.out.println(userlist.get(0).toString());
        log.info("注解形式结束------");
    }

    @Test
    public void testCustomXml() {
        User user = new User();
        user.setCode("902");
        user.setName("okong-sql");
        user.insert();
        List<User> userlist = userDao.selectUserCustomParamsByXml(user.getCode());
        //由于新增的 肯定不为null 故不判断了。
        System.out.println(userlist.get(0).toString());
        log.info("xml形式结束------");
    }

}

==注意:==
在使用spring-boot-maven-plugin插件打包成springboot运行jar时,需要注意:由于springboot的jar扫描路径方式问题,会导致别名的包未扫描到,所以这个只需要把mybatis默认的扫描设置为Springboot的VFS实现.修改spring-mybatis.xml文件:

  <!--mybatis-->
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 自动扫描mapper.xml文件,支持通配符 -->
        <property name="mapperLocations" value="classpath:mapper/**/*.xml"/>
        <!-- 配置文件,比如参数配置(是否启动驼峰等)、插件配置等 -->
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <!-- 启用别名,这样就无需写全路径类名了,具体可自行查阅资料 -->
        <property name="typeAliasesPackage" value="cn.lqdev.learning.mybatisplus.samples.biz.entity"/>
        <!-- MP 全局配置注入 -->
        <property name="globalConfig" ref="globalConfig"/>
        <!-- 设置vfs实现,避免路径扫描问题 -->
        <property name="vfs"  value="com.baomidou.mybatisplus.spring.boot.starter.SpringBootVFS"></property>
    </bean>
分页插件,性能分析插件

mybatis的插件机制使用只需要注册即可

  • mybatis-config.xml
    <plugins>
      <!-- SQL 执行性能分析,开发环境使用,线上不推荐。 -->
      <plugin interceptor="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"></plugin>
      <!-- 分页插件配置 -->
      <plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></plugin>
    </plugins>
  • 分页测试类(性能分析,配置后可以输出sql及取数时间):
@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest 
@Slf4j
public class PluginTest {

    @Autowired
    IUserService userService;

    @Test
    public void testPagination() {
        Page<User> page = new Page<>();
        //每页数
        page.setSize(10);
        //当前页码
        page.setCurrent(1);

        //无条件时
        Page<User> pageList = userService.selectPage(page);
        System.out.println(pageList.getRecords().get(0));

        //新增数据 避免查询不到数据
        User user = new User();
        user.setCode("801");
        user.setName("okong-Pagination");
        user.insert();
        //加入条件构造器
        EntityWrapper<User> qryWapper = new EntityWrapper<>();
        //这里也能直接设置 entity 这是条件就是entity的非空字段值了
//        qryWapper.setEntity(user);
        //这里建议直接用 常量 
    //    qryWapper.eq(User.CODE, user.getCode());
        pageList = userService.selectPage(page, qryWapper);
        System.out.println(pageList.getRecords().get(0));
        log.info("分页结束");
    }

}
  • 性能插件体现,控制台输出:
 Time:4 ms - ID:cn.lqdev.learning.mybatisplus.samples.biz.dao.UserDao.selectPage
 Execute SQL: SELECT id AS id,code,`name`,`status`,gmt_create AS gmtCreate,gmt_modified AS gmtModified FROM user WHERE id=1026120705692434433 AND code='801' AND `name`='okong-Pagination' LIMIT 0,10
公共字段自动填充

通常,每个公司都有自己的表定义,在《阿里巴巴Java开发手册》中,就强制规定表必备三字段:id,gmt_create,gmt_modified.所以通常我们都会写个公共的拦截器去实现自动填充比如创建时间和更新时间的,无需开发人员手动设置.而在MP中就提供了这么一个公共字段自动填充功能

  • 设置填充字段的填充类型:
  • User

==注意==可以在代码生成器里面配置规则的,可自动配置

    /**
     * 创建时间
     */
    @TableField(fill=FieldFill.INSERT)
    private Date gmtCreate;
    /**
     * 修改时间
     */
    @TableField(fill=FieldFill.INSERT_UPDATE)
    private Date gmtModified;
  • 定义处理类:
  • MybatisObjectHandler
public class MybatisObjectHandler extends MetaObjectHandler{

    @Override
    public void insertFill(MetaObject metaObject) {
        //新增时填充的字段
        setFieldValByName("gmtCreate", new Date(), metaObject);
        setFieldValByName("gmtModified", new Date(), metaObject);

    }

    @Override
    public void updateFill(MetaObject metaObject) {
        //更新时 需要填充字段
        setFieldValByName("gmtModified", new Date(), metaObject);
    }
}
  • 修改springb-mybatis.xml文件,加入此配置
    <bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
        <!--
            AUTO->`0`("数据库ID自增")QW
             INPUT->`1`(用户输入ID")
            ID_WORKER->`2`("全局唯一ID")
            UUID->`3`("全局唯一ID")
        -->
        <property name="idType" value="2" />
        <property name="metaObjectHandler" ref="mybatisObjectHandler"></property>
    </bean>

    <bean id="mybatisObjectHandler" class="cn.lqdev.learning.mybatisplus.samples.config.MybatisObjectHandler"/>

再新增或者修改时,对应时间就会进行更新:

 Time:31 ms - ID:cn.lqdev.learning.mybatisplus.samples.biz.dao.UserDao.insert
 Execute SQL: INSERT INTO user ( id, code, `name`, gmt_create,gmt_modified ) VALUES ( 1026135016838037506, '702', 'okong-condition', '2018-08-05 23:57:07.344','2018-08-05 23:57:07.344' )
相关文章
|
5月前
|
SQL 缓存 Java
Mybatis及MybatisPlus
MyBatis 是一款优秀的持久层框架,支持自定义 SQL、存储过程及高级映射。其系统架构通过 mybatis-config.xml 配置全局信息,结合 mapper.xml 映射 SQL 语句,构建 SqlSessionFactory 并创建 SqlSession 操作数据库。MyBatis 底层通过 Executor 执行器和 Mapped Statement 对象实现 SQL 的输入输出映射与执行。支持复杂结果集映射,
|
6月前
|
Java 数据库连接 API
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
280 1
|
5月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
179 0
|
7月前
|
SQL Java 数据安全/隐私保护
发现问题:Mybatis-plus的分页总数为0,分页功能失效,以及多租户插件的使用。
总的来说,使用 Mybatis-plus 确实可以极大地方便我们的开发,但也需要我们理解其工作原理,掌握如何合适地使用各种插件。分页插件和多租户插件是其中典型,它们的运用可以让我们的代码更为简洁、高效,理解和掌握好它们的用法对我们的开发过程有着极其重要的意义。
757 15
|
8月前
|
SQL 存储 Java
Mybatis源码解析:详述初始化过程
以上就是MyBatis的初始化过程,这个过程主要包括SqlSessionFactory的创建、配置文件的解析和加载、映射文件的加载、SqlSession的创建、SQL的执行和SqlSession的关闭。这个过程涉及到了MyBatis的核心类和接口,包括SqlSessionFactory、SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、Configuration、SqlSession和Executor等。通过这个过程,我们可以看出MyBatis的灵活性和强大性,它可以很好地支持定制化SQL、存储过程以及高级映射,同时也避免了几
162 20
|
9月前
|
Java 关系型数据库 数据库连接
Javaweb之Mybatis入门程序的详细解析
本文详细介绍了一个MyBatis入门程序的创建过程,从环境准备、Maven项目创建、MyBatis配置、实体类和Mapper接口的定义,到工具类和测试类的编写。通过这个示例,读者可以了解MyBatis的基本使用方法,并在实际项目中应用这些知识。
233 11
|
10月前
|
Java 数据库连接 Spring
MyBatis-Plus关键功能使用
通过本文的详细介绍,您可以系统地了解并掌握MyBatis-Plus的关键功能,进一步提高开发效率和代码质量。
417 23
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
1465 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
SQL Java 数据库连接
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
|
9月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
947 29