MyBatis-Plus的简单使用

时间:2022-03-09 03:08:09

  mybatis-plus也只是听过,可是终究没有使用过。于是自己花几天晚上的时间研究mybatis-plus的使用。

  下面的研究也是基于其官网:http://mp.baomidou.com/guide/  。官网的介绍非常详细。

  官网有基于springboot,也有基于spring的原始方式。下面基于原始的spring配置方式进行使用。如果有时间,将来会将自己的SSM项目转为springboot项目,并且整合MP与Redis缓存等操作。。。。。。。

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

0.pom.xml配置:

引入下面maven依赖之后会自动引入mybatis与mybats-spring,所以需要把原来的删掉

        <dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.0.1</version>
</dependency>

1.前期的环境搭建工作

参考:https://baomidou.gitee.io/mybatis-plus-doc/#/install

1.1我先附上原生的mybatis整合spring以及整合pagehelper插件的xml中的配置,然后两个做对比。

    <!-- 0.连接池属性设置读取指定的properties文件 -->
<context:property-placeholder location="classpath:db.properties" ignore-unresolvable="true"/> <!-- 1.将连接池放入spring容器 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean> <!--2. 配置 Mybatis的会话工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置Mybatis的核心 配置文件所在位置 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml" />
<!-- 注意其他配置 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
helperDialect=mysql
reasonable=true
</value>
</property>
</bean>
</array>
</property>
</bean> <!-- 3.2通过MapperScannerConfigurer扫描进行批量生成代理对象
遵循规范:mapper.java和mapper.xml名字一样且在同一个目录下
自动扫描出来的代理对象的id为mapper类类名(首字母小写)
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定扫描的包名,如果有多个,用半角逗号分隔 -->
<property name="basePackage" value="cn.xm.jwxt.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>

1.2    MP整合的配置

下面配置可以替换上面1.1中的配置。但是需要注意分页由于是引用了MP的分页插件,所以会导致原来pagehelper的分页插件不生效。但是原来手写的mapper.xml是生效的,可以说是整合成功。

    <!-- 0.连接池属性设置读取指定的properties文件 -->
<context:property-placeholder location="classpath:db.properties" ignore-unresolvable="true"/> <!-- 1.将连接池放入spring容器 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean> <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 配置实体扫描路径,多个package可以用分号; 逗号, 分隔, 支持通配符*-->
<!-- com.a.b.entity;com.a.c.entity;com.d.*.entity-->
<property name="typeAliasesPackage" value="cn.xm.jwxt.bean.*"/>
<property name="configuration" ref="mybatisConfig"/>
<!-- MP 全局配置注入 -->
<property name="globalConfig" ref="globalConfig"/>
<property name="plugins">
<array>
<!-- 分页插件配置 -->
<bean id="paginationInterceptor"
class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
<!-- 性能拦截器,兼打印sql,不建议生产环境配置-->
<bean id="performanceInterceptor"
class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"/>
</array>
</property>
</bean> <bean id="mybatisConfig" class="com.baomidou.mybatisplus.MybatisConfiguration">
<property name="mapUnderscoreToCamelCase" value="true"/>
</bean> <!-- 定义 MP 全局策略 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 主键策略配置 -->
<!-- 可选参数
AUTO->`0`("数据库ID自增")
INPUT->`1`(用户输入ID")
ID_WORKER->`2`("全局唯一ID")
UUID->`3`("全局唯一ID")
-->
<property name="idType" value="2"/> <!-- 数据库类型配置 -->
<!-- 可选参数(默认mysql)
MYSQL->`mysql`
ORACLE->`oracle`
DB2->`db2`
H2->`h2`
HSQL->`hsql`
SQLITE->`sqlite`
POSTGRE->`postgresql`
SQLSERVER2005->`sqlserver2005`
SQLSERVER->`sqlserver`
-->
<property name="dbType" value="mysql"/> <!-- 全局表为下划线命名设置 true -->
<property name="dbColumnUnderline" value="true"/>
</bean> <!-- 配置mybatis 扫描mapper接口的路径, 相当于注解@MapperScan,@MapperScan("com.baomidou.mybatisplus.test.h2.entity.mapper")-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.xm.jwxt.mapper"/>
</bean>

为了使用pageHelper的分页插件,我们尝试将pageHelper的分页插件加入上面sqlsessionfactory中

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 配置实体扫描路径,多个package可以用分号; 逗号, 分隔, 支持通配符*-->
<!-- com.a.b.entity;com.a.c.entity;com.d.*.entity-->
<property name="typeAliasesPackage" value="cn.xm.jwxt.bean.*"/>
<property name="configuration" ref="mybatisConfig"/>
<!-- MP 全局配置注入 -->
<property name="globalConfig" ref="globalConfig"/>
<property name="plugins">
<array>
<!-- pageHelper的分页插件配置 -->
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
helperDialect=mysql
reasonable=true
</value>
</property>
</bean>
<!--MP自带的分页插件-->
<bean id="paginationInterceptor"
class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
<!-- 性能拦截器,兼打印sql,不建议生产环境配置-->
<bean id="performanceInterceptor"
class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"/>
</array>
</property>
</bean>

经过证明上面的配置是可以的。也就是我们可以用原来的pagehelper插件。

而且SQL性能拦截器也生效,如下:

MyBatis-Plus的简单使用

虽然mybatis的日志功能也可以打出SQL以及参数,但是没有这个强大,下面是mybatis整合slf4j打出的SQL:

MyBatis-Plus的简单使用

2.主要常见的功能简单使用

2.1代码生成器----逆向工程,类似于mybatis的generator

package cn.xm.jwxt.utils;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
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.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import java.util.HashMap;
import java.util.Map; /**
* <p>
* 代码生成器演示
* </p>
*/
public class MpGenerator { /**
* <p>
* MySQL 生成演示
* </p>
*/
public static void main(String[] args) {
AutoGenerator mpg = new AutoGenerator();
// 选择 freemarker 引擎,默认 Veloctiy
// mpg.setTemplateEngine(new FreemarkerTemplateEngine()); // 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("G://MP");
gc.setFileOverride(true);
gc.setActiveRecord(false);// 不需要ActiveRecord特性的请改为false
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
// .setKotlin(true) 是否生成 kotlin 代码
gc.setAuthor("qlq"); // 自定义文件命名,注意 %s 会自动填充表实体属性!
// gc.setMapperName("%sDao");
// gc.setXmlName("%sDao");
// gc.setServiceName("MP%sService");
// gc.setServiceImplName("%sServiceDiy");
// gc.setControllerName("%sAction");
mpg.setGlobalConfig(gc); // 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("sa");
dsc.setPassword("123456");
dsc.setUrl("jdbc:mysql://localhost:3306/jwxt");
mpg.setDataSource(dsc); // 策略配置
StrategyConfig strategy = new StrategyConfig();
// strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
strategy.setTablePrefix(new String[] { "tlog_", "tsys_" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
// strategy.setInclude(new String[] { "user" }); // 需要生成的表
// strategy.setExclude(new String[]{"test"}); // 排除生成的表
// 自定义实体父类
// strategy.setSuperEntityClass("com.baomidou.demo.TestEntity");
// 自定义实体,公共字段
// strategy.setSuperEntityColumns(new String[] { "test_id", "age" });
// 自定义 mapper 父类
// strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
// 自定义 service 父类
// strategy.setSuperServiceClass("com.baomidou.demo.TestService");
// 自定义 service 实现类父类
// strategy.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl");
// 自定义 controller 父类
// strategy.setSuperControllerClass("com.baomidou.demo.TestController");
// 【实体】是否生成字段常量(默认 false)
// public static final String ID = "test_id";
// strategy.setEntityColumnConstant(true);
// 【实体】是否为构建者模型(默认 false)
// public User setName(String name) {this.name = name; return this;}
// strategy.setEntityBuilderModel(true);
mpg.setStrategy(strategy); // 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("cn.xm.mapper");
pc.setModuleName("module");
mpg.setPackageInfo(pc); // 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
InjectionConfig cfg = 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);
}
};
mpg.setCfg(cfg); // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改,
// 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称
// TemplateConfig tc = new TemplateConfig();
// tc.setController("...");
// tc.setEntity("...");
// tc.setMapper("...");
// tc.setXml("...");
// tc.setService("...");
// tc.setServiceImpl("...");
// 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
// mpg.setTemplate(tc); // 执行生成
mpg.execute(); // 打印注入设置【可无】
System.err.println(mpg.getCfg().getMap().get("abc"));
} }

  下面贴出生成的代码的结构:看的出来MP导出的时候是以模块进行分隔的,也就是先模块后三层架构,我习惯是先三层架构后模块(看目录名称就知道对应目录的东西),比mybatis的generator强大的是生成了对应的service目录和web目录,同时生成了对应的文件,都省下我们手写了。而且也可以指定生成哪些表或者不生成哪些表。

MyBatis-Plus的简单使用

 我们查看mapper和一个文件:(没有任何抽象方法,XML也没有任何SQL)

MyBatis-Plus的简单使用

package cn.xm.mapper.module.mapper;

import cn.xm.mapper.module.entity.ApArrangeCourseAudit;
import com.baomidou.mybatisplus.mapper.BaseMapper; /**
* <p>
* Mapper 接口
* </p>
*
* @author qlq
* @since 2018-11-20
*/
public interface ApArrangeCourseAuditMapper extends BaseMapper<ApArrangeCourseAudit> { }
<?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="cn.xm.mapper.module.mapper.ApArrangeCourseAuditMapper"> <!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.xm.mapper.module.entity.ApArrangeCourseAudit">
<id column="audit_id" property="audit_id" />
<result column="arrange_task_id" property="arrange_task_id" />
<result column="auditor_name" property="auditor_name" />
<result column="auditor_id" property="auditor_id" />
<result column="audit_time" property="audit_time" />
<result column="audit_suggestion" property="audit_suggestion" />
<result column="audit_result" property="audit_result" />
<result column="remark" property="remark" />
</resultMap> </mapper>

查看service目录和一个文件

MyBatis-Plus的简单使用

package cn.xm.mapper.module.service;

import cn.xm.mapper.module.entity.ApArrangeCourseAudit;
import com.baomidou.mybatisplus.service.IService; /**
* <p>
* 服务类
* </p>
*
* @author qlq
* @since 2018-11-20
*/
public interface IApArrangeCourseAuditService extends IService<ApArrangeCourseAudit> { }
package cn.xm.mapper.module.service.impl;

import cn.xm.mapper.module.entity.ApArrangeCourseAudit;
import cn.xm.mapper.module.mapper.ApArrangeCourseAuditMapper;
import cn.xm.mapper.module.service.IApArrangeCourseAuditService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service; /**
* <p>
* 服务实现类
* </p>
*
* @author qlq
* @since 2018-11-20
*/
@Service
public class ApArrangeCourseAuditServiceImpl extends ServiceImpl<ApArrangeCourseAuditMapper, ApArrangeCourseAudit> implements IApArrangeCourseAuditService { }

 查看web目录以及查看文件:

MyBatis-Plus的简单使用

package cn.xm.mapper.module.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; /**
* <p>
* 前端控制器
* </p>
*
* @author qlq
* @since 2018-11-20
*/
@Controller
@RequestMapping("/module/apArrangeCourseAudit")
public class ApArrangeCourseAuditController { } 

发现上面的控制层模板默认是SpringMVC。

上面Generator中可以设置这些的默认模板,我们可以拷贝一个出来然后进行修改

        // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改,
// 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称
// TemplateConfig tc = new TemplateConfig();
// tc.setController("...");
// tc.setEntity("...");
// tc.setMapper("...");
// tc.setXml("...");
// tc.setService("...");
// tc.setServiceImpl("...");
// 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
// mpg.setTemplate(tc);

查看  TemplateConfig 类:

MyBatis-Plus的简单使用

我们再查看/template/controller.java.vm内容:

package ${package.Controller};

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end /**
* <p>
* ${table.comment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
@Controller
@RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/${table.entityPath}")
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
#end }

看了上面源码之后如果想修改模板就很简单了。

2..研究MP的基本的增删改查

实际其超类   BaseMapper 已经包括了好多成熟的方法,类似hebernatetemplate,封装了基本的增删改查以及查询所有等操作。

关于其超类包装的方法只列出接口的抽象方法,具体的实现可以参考源码:

Dao层超类Mapper封装的基本方法。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package com.baomidou.mybatisplus.mapper; import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds; public interface BaseMapper<T> {
Integer insert(T var1); Integer deleteById(Serializable var1); Integer deleteByMap(@Param("cm") Map<String, Object> var1); Integer delete(@Param("ew") Wrapper<T> var1); Integer deleteBatchIds(List<? extends Serializable> var1); Integer updateById(T var1); Integer update(@Param("et") T var1, @Param("ew") Wrapper<T> var2); T selectById(Serializable var1); List<T> selectBatchIds(List<? extends Serializable> var1); List<T> selectByMap(@Param("cm") Map<String, Object> var1); T selectOne(@Param("ew") T var1); Integer selectCount(@Param("ew") Wrapper<T> var1); List<T> selectList(@Param("ew") Wrapper<T> var1); List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> var1); List<Object> selectObjs(@Param("ew") Wrapper<T> var1); List<T> selectPage(RowBounds var1, @Param("ew") Wrapper<T> var2); List<Map<String, Object>> selectMapsPage(RowBounds var1, @Param("ew") Wrapper<T> var2);
}

上面的wrapper是mybatis封装查询条件的超类,在本版本的MP中是用EntityWrapper封装条件。

下面研究简单的使用:

0.环境准备:(导出一个表即可)

package cn.xm.jwxt.ceshi;

import java.util.HashMap;
import java.util.Map; import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
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.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; /**
* <p>
* 代码生成器演示
* </p>
*/
public class MpGenerator { /**
* <p>
* MySQL 生成演示
* </p>
*/
public static void main(String[] args) {
AutoGenerator mpg = new AutoGenerator();
// 选择 freemarker 引擎,默认 Veloctiy
// mpg.setTemplateEngine(new FreemarkerTemplateEngine()); // 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("G://MP");
gc.setFileOverride(true);
gc.setActiveRecord(false);// 不需要ActiveRecord特性的请改为false
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
// .setKotlin(true) 是否生成 kotlin 代码
gc.setAuthor("qlq"); // 自定义文件命名,注意 %s 会自动填充表实体属性!
// gc.setMapperName("%sDao");
// gc.setXmlName("%sDao");
// gc.setServiceName("MP%sService");
// gc.setServiceImplName("%sServiceDiy");
// gc.setControllerName("%sAction");
mpg.setGlobalConfig(gc); // 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setUrl("jdbc:mysql://localhost:3306/jwxt");
mpg.setDataSource(dsc); // 策略配置
StrategyConfig strategy = new StrategyConfig();
// strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
// strategy.setTablePrefix(new String[] { "tlog_", "tsys_" });// 此处可以修改为您的表前缀
// strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[] { "user" }); // 需要生成的表
// strategy.setExclude(new String[]{"test"}); // 排除生成的表
// 自定义实体父类
// strategy.setSuperEntityClass("com.baomidou.demo.TestEntity");
// 自定义实体,公共字段
// strategy.setSuperEntityColumns(new String[] { "test_id", "age" });
// 自定义 mapper 父类
// strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
// 自定义 service 父类
// strategy.setSuperServiceClass("com.baomidou.demo.TestService");
// 自定义 service 实现类父类
// strategy.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl");
// 自定义 controller 父类
// strategy.setSuperControllerClass("com.baomidou.demo.TestController");
// 【实体】是否生成字段常量(默认 false)
// public static final String ID = "test_id";
// strategy.setEntityColumnConstant(true);
// 【实体】是否为构建者模型(默认 false)
// public User setName(String name) {this.name = name; return this;}
// strategy.setEntityBuilderModel(true);
mpg.setStrategy(strategy); // 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("cn.xm.jwxt");
pc.setModuleName("ceshi");
mpg.setPackageInfo(pc); // 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
InjectionConfig cfg = 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);
}
};
mpg.setCfg(cfg); // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改,
// 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称
// TemplateConfig tc = new TemplateConfig();
// tc.setController("...");
// tc.setEntity("...");
// tc.setMapper("...");
// tc.setXml("...");
// tc.setService("...");
// tc.setServiceImpl("...");
// 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
// mpg.setTemplate(tc); // 执行生成
mpg.execute(); // 打印注入设置【可无】
System.err.println(mpg.getCfg().getMap().get("abc"));
} }

applicationContext-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd "> <!-- 0.连接池属性设置读取指定的properties文件 -->
<context:property-placeholder location="classpath:db.properties" ignore-unresolvable="true"/> <!-- 1.将连接池放入spring容器 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean> <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 配置实体扫描路径,多个package可以用分号; 逗号, 分隔, 支持通配符*-->
<!-- com.a.b.entity;com.a.c.entity;com.d.*.entity-->
<property name="typeAliasesPackage" value="cn.xm.jwxt.*"/>
<property name="configuration" ref="mybatisConfig"/>
<!-- MP 全局配置注入 -->
<property name="globalConfig" ref="globalConfig"/>
<property name="plugins">
<array>
<!-- pageHelper的分页插件配置 -->
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
helperDialect=mysql
reasonable=true
</value>
</property>
</bean>
<!--MP自带的分页插件-->
<bean id="paginationInterceptor"
class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
<!-- 性能拦截器,兼打印sql,不建议生产环境配置-->
<bean id="performanceInterceptor"
class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"/>
</array>
</property>
</bean> <bean id="mybatisConfig" class="com.baomidou.mybatisplus.MybatisConfiguration">
<property name="mapUnderscoreToCamelCase" value="false"/>
</bean> <!-- 定义 MP 全局策略 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 主键策略配置 -->
<!-- 可选参数
AUTO->`0`("数据库ID自增")
INPUT->`1`(用户输入ID")
ID_WORKER->`2`("全局唯一ID")
UUID->`3`("全局唯一ID")
-->
<property name="idType" value="1"/> <!-- 数据库类型配置 -->
<!-- 可选参数(默认mysql)
MYSQL->`mysql`
ORACLE->`oracle`
DB2->`db2`
H2->`h2`
HSQL->`hsql`
SQLITE->`sqlite`
POSTGRE->`postgresql`
SQLSERVER2005->`sqlserver2005`
SQLSERVER->`sqlserver`
-->
<property name="dbType" value="mysql"/> <!-- 全局表为下划线命名设置 true -->
<property name="dbColumnUnderline" value="false"/>
</bean> <!-- 配置mybatis 扫描mapper接口的路径, 相当于注解@MapperScan,@MapperScan("com.baomidou.mybatisplus.test.h2.entity.mapper")-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.xm.jwxt"/>
</bean> <!-- 4.配置事务管理器 -->
<!-- 事务核心管理器,封装了事务操作,依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 5.开启注解管理aop事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!-- 6.开启注解AOP (前提是引入aop命名空间和相关jar包) -->
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"></aop:aspectj-autoproxy> <!-- 7.开启aop,对类代理强制使用cglib代理 -->
<aop:config proxy-target-class="true"></aop:config> <!-- 8.扫描 @Service @Component 注解-->
<context:component-scan base-package="cn.xm.jwxt" ></context:component-scan> </beans>

注意:对导出的表的实体,最好加上主键列在数据库中的列名称,否则调用MP自己的方法设计到主键操作的时候会报错语句绑定错误。如下

MyBatis-Plus的简单使用

1.测试简单的增加:

package cn.xm.jwxt.ceshi;

import java.sql.SQLException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import cn.xm.jwxt.ceshi.entity.User;
import cn.xm.jwxt.ceshi.mapper.UserMapper; /**
* @Author: qlq
* @Description
* @Date: 22:06 2018/11/22
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application*.xml")
public class MpTest {
@Autowired
private UserMapper userMapper1; @Test
public void test1() throws SQLException {
User user = new User();
user.setUserName("username");
user.setUserID("ceshi");
user.setPassword("111222");
userMapper1.insert(user);
}
}

结果:

 Time:581 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.insert
SQL Params:['ceshi', 'username', '111222']
Execute SQL:INSERT INTO user ( userID, userName, `password` ) VALUES ( ?, ?, ? )

2.测试查询

(0)调用MP自己的根据主键查询,查询单个和查询多个

    @Test
public void test1() throws SQLException {
// 查询单个
User selectById = userMapper1.selectById("ceshi");
System.out.println(selectById);
// 批量查询
List<String> idList = new ArrayList<String>();
idList.add("ceshi");
idList.add("ceshi2");
List<User> selectBatchIds = userMapper1.selectBatchIds(idList);
System.out.println(selectBatchIds); // 根据map条件查询,map中封装的是数据的列的条件
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("userId", "ceshi");
List<User> selectByMap = userMapper1.selectByMap(columnMap);
System.out.println(selectByMap);
}

结果:

mybatis-plus init success.
Time:235 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectById
SQL Params:['ceshi']
Execute SQL:SELECT userId AS userID,userCode,userName,`password`,userSort,userStuTeaNum,userUnitName,userUnitNum,isUse,remark1 FROM user WHERE userId=?

User [userID=ceshi, userCode=null, userName=username, password=111222, userSort=null, userStuTeaNum=null, userUnitName=null, userUnitNum=null, isUse=null, remark1=null]
Time:16 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectBatchIds
SQL Params:['ceshi', 'ceshi2']
Execute SQL:SELECT userId AS userID,userCode,userName,`password`,userSort,userStuTeaNum,userUnitName,userUnitNum,isUse,remark1 FROM user WHERE userId IN ( ? , ? )

[User [userID=ceshi, userCode=null, userName=username, password=111222, userSort=null, userStuTeaNum=null, userUnitName=null, userUnitNum=null, isUse=null, remark1=null], User [userID=ceshi2, userCode=null, userName=username, password=111222, userSort=null, userStuTeaNum=null, userUnitName=null, userUnitNum=null, isUse=null, remark1=null]]
Time:20 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectByMap
SQL Params:['ceshi']
Execute SQL:SELECT userId AS userID,userCode,userName,`password`,userSort,userStuTeaNum,userUnitName,userUnitNum,isUse,remark1 FROM user WHERE userId = ?

[User [userID=ceshi, userCode=null, userName=username, password=111222, userSort=null, userStuTeaNum=null, userUnitName=null, userUnitNum=null, isUse=null, remark1=null]]

(1)封装Wrapper进行查询:

    @Test
public void test1() throws SQLException {
// 批量查询
// 构造实体对应的 EntityWrapper 对象,进行过滤查询
EntityWrapper<User> ew = new EntityWrapper<>();
ew.where("userId={0}", "ceshi").like("username", "user");
List<User> selectList = userMapper1.selectList(ew);
System.out.println(selectList);
}

我们查看 EntityWrapper 的源码: (其更多的方法是封装在其父类Wrapper中 )

/** <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao. */
package com.baomidou.mybatisplus.mapper;
import com.baomidou.mybatisplus.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.toolkit.StringUtils; /**
* <p>
* Entity 对象封装操作类,定义T-SQL语法
* </p>
*
* @author hubin , yanghu , Dyang , Caratacus
* @Date 2016-11-7
*/
@SuppressWarnings("serial")
public class EntityWrapper<T> extends Wrapper<T> { /**
* 拼接WHERE后应该是AND还是OR
*/
private String AND_OR = "AND";
/**
* 数据库表映射实体类
*/
protected T entity = null; public EntityWrapper() {
/* 注意,传入查询参数 */
} public EntityWrapper(T entity) {
this.entity = entity;
} public EntityWrapper(T entity, String sqlSelect) {
this.entity = entity;
this.sqlSelect = sqlSelect;
} public T getEntity() {
return entity;
} public void setEntity(T entity) {
this.entity = entity;
} /**
* <p>
* 添加OR条件
* </p>
*
* @param sqlOr
* or 条件语句
* @param params
* 参数集
* @return this
*/
@Override
public Wrapper<T> or(String sqlOr, Object... params) {
if (StringUtils.isEmpty(sql.toString())) {
AND_OR = "OR";
}
super.or(sqlOr, params);
return this;
} /**
* <p>
* 使用OR换行,并添加一个带()的新的条件
* </p>
* <p>
* eg: ew.where("name='zhangsan'").and("id=11").orNew("statu=1"); 输出: WHERE
* (name='zhangsan' AND id=11) OR (statu=1)
* </p>
*
* @param sqlOr
* AND 条件语句
* @param params
* 参数值
* @return this
*/
@Override
public Wrapper<T> orNew(String sqlOr, Object... params) {
if (StringUtils.isEmpty(sql.toString())) {
AND_OR = "OR";
}
super.orNew(sqlOr, params);
return this;
} /**
* SQL 片段
*/
@Override
public String getSqlSegment() {
/*
* 无条件
*/
String sqlWhere = sql.toString();
if (StringUtils.isEmpty(sqlWhere)) {
return null;
} /*
* 根据当前实体判断是否需要将WHERE替换成 AND 增加实体不为空但所有属性为空的情况
*/
sqlWhere = ReflectionKit.checkFieldValueNotNull(entity) ? sqlWhere.replaceFirst("WHERE", AND_OR) : sqlWhere;
return sqlWhere;
} }

补充:wrapper还有好对条件可以使用,in、order等都可以,例如:

        EntityWrapper<User> ew = new EntityWrapper<>();
ew.where("userId={0}", "ceshi").like("username", "user").in("", new ArrayList<>()).exists("")
.setSqlSelect(" xx = xx").orderBy("sss", false).notIn("", new ArrayList<>());

 (2)分页查询(实际是逻辑分页,全部查出之后进行筛选)

        // 传一个空对象或者传null查所有
EntityWrapper<User> ew = new EntityWrapper<>();
ew.orderBy("userId");
Integer selectCount = userMapper1.selectCount(ew);
System.out.println(selectCount); List<User> selectPage = userMapper1.selectPage(new RowBounds(0, 5), ew);
System.out.println(selectPage);

结果::

mybatis-plus init success.
Time:240 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectCount
SQL Params:[]
Execute SQL:SELECT COUNT(1) FROM user ORDER BY userId

8
Time:31 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectPage
SQL Params:[]
Execute SQL:SELECT userId AS userID,userCode,userName,`password`,userSort,userStuTeaNum,userUnitName,userUnitNum,isUse,remark1 FROM user ORDER BY userId

Page{count=false, pageNum=1, pageSize=5, startRow=0, endRow=5, total=-1, pages=1, reasonable=false, pageSizeZero=false}

 

(3)查询结果映射为Map的查询方法:

        List<Map<String, Object>> selectMaps = userMapper1.selectMaps(null);
System.out.println(selectMaps); List<Map<String, Object>> selectMapsPage = userMapper1.selectMapsPage(new RowBounds(0, 5), null);
System.out.println(selectMapsPage);

结果:

mybatis-plus init success.
[{userID=3c51dd8f9dc04315b97a34f9a939f3b9, userCode=2014223, isUse=1, userName=lll, userUnitNum=Soft0102, password=123456, userUnitName=软件工程教研室111, userSort=教师}, {userID=5ea97f30d605410da4e00df52c2fedc4, userCode=院长, isUse=1, userName=院长, userUnitNum=无, password=123, userUnitName=无, userSort=教师}, {userID=a9e65788297e4a8cb68a369522ee5af7, userCode=123, isUse=1, userName=培养方案, userUnitNum=无, password=123, userUnitName=无, userSort=教师}, {userID=b33b938faada40aeac2b5ca228336473, userCode=root, isUse=1, userName=超级管理员, userUnitNum=超管, password=root, userUnitName=超管, userSort=教师}, {userID=c43aeab8a15c427e81fda9b6e55571c4, userCode=教研室主任, isUse=1, userName=教研室主任, userUnitNum=无, password=123, userUnitName=无, userSort=教师}, {userID=ceshi, userName=username, password=111222}, {userID=ceshi2, userName=username, password=111222}, {userID=e0973fd895bf4d93bd116f18512b461b, userCode=1, isUse=1, userName=1, userUnitNum=无, password=1, userUnitName=无, userSort=学生}]
Time:349 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectMaps
SQL Params:[]
Execute SQL:SELECT userId AS userID,userCode,userName,`password`,userSort,userStuTeaNum,userUnitName,userUnitNum,isUse,remark1 FROM user

Page{count=false, pageNum=1, pageSize=5, startRow=0, endRow=5, total=-1, pages=1, reasonable=false, pageSizeZero=false}
Time:30 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.selectMapsPage
SQL Params:[]
Execute SQL:SELECT userId AS userID,userCode,userName,`password`,userSort,userStuTeaNum,userUnitName,userUnitNum,isUse,remark1 FROM user

3.MP进行修改

    @Test
public void test1() throws SQLException {
// 修改单个
User entity = new User();
entity.setUserID("ceshi");
entity.setUserName("userName2");
userMapper1.updateById(entity); // 批量修改,第二个是条件
User entity2 = new User();
entity2.setPassword("8888");
Integer update = userMapper1.update(entity2, new EntityWrapper<User>());
}

查看打出的SQL:

mybatis-plus init success.
Time:236 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.updateById
SQL Params:['userName2', 'ceshi']
Execute SQL:UPDATE user SET userName=? WHERE userId=?

Time:250 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.update
SQL Params:['8888']
Execute SQL:UPDATE user SET `password`=?

4.MP进行删除

        // 删除单个
Integer deleteById = userMapper1.deleteById("ceshi");
// 批量删除
List<String> idList = new ArrayList<>();
idList.add("ceshi");
idList.add("ceshi2");
Integer deleteBatchIds = userMapper1.deleteBatchIds(idList);
// 根据列批量删除
Map<String, Object> condition = new HashMap<>();
condition.put("username", "username");
Integer deleteByMap = userMapper1.deleteByMap(condition);
// Wrapper传条件删除
EntityWrapper ew = new EntityWrapper<User>();
ew.and("username={0}", "username");
Integer delete = userMapper1.delete(ew);

结果:

mybatis-plus init success.
Time:326 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.deleteById
SQL Params:['ceshi']
Execute SQL:DELETE FROM user WHERE userId=?

Time:147 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.deleteBatchIds
SQL Params:['ceshi', 'ceshi2']
Execute SQL:DELETE FROM user WHERE userId IN ( ? , ? )

Time:4 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.deleteByMap
SQL Params:['username']
Execute SQL:DELETE FROM user WHERE username = ?

Time:4 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.delete
SQL Params:[]
Execute SQL:DELETE FROM user WHERE (username='username')

3.测试自定义方法与xml写SQL进行dao操作

与普通的mybatis开发一样,也是接口中声明方法,XML中写对应的SQL

(1)mapper中声明接口

package cn.xm.jwxt.ceshi.mapper;

import cn.xm.jwxt.ceshi.entity.User;

import org.apache.ibatis.annotations.Param;

import com.baomidou.mybatisplus.mapper.BaseMapper;

/**
* <p>
* Mapper 接口
* </p>
*
* @author qlq
* @since 2018-11-24
*/
public interface UserMapper extends BaseMapper<User> { public User select(@Param("id") String idString); }

(2)xml中写SQL

<?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="cn.xm.jwxt.ceshi.mapper.UserMapper"> <!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.xm.jwxt.ceshi.entity.User">
<id column="userID" property="userID" />
<result column="userCode" property="userCode" />
<result column="userName" property="userName" />
<result column="password" property="password" />
<result column="userSort" property="userSort" />
<result column="userStuTeaNum" property="userStuTeaNum" />
<result column="userUnitName" property="userUnitName" />
<result column="userUnitNum" property="userUnitNum" />
<result column="isUse" property="isUse" />
<result column="remark1" property="remark1" />
</resultMap> <select id="select" parameterType="string" resultType="user">
select *
from user where userId = #{id}
</select> </mapper>

(3)测试

    @Test
public void test1() throws SQLException {
User select = userMapper1.select("ceshi");
System.out.println(select);
}

结果:

Time:440 ms - ID:cn.xm.jwxt.ceshi.mapper.UserMapper.select
SQL Params:['ceshi']
Execute SQL:select * from user where userId = ?

cn.xm.jwxt.ceshi.entity.User@1f7c1b71

总结:用mybatis-plus进行开发的时候,对原来的功能是没有影响的,也就是说如果一个项目原来使用的是mybatis,想使用上mybatis-plus是完全可以的。

  mybatis也支持原来的mybatis逆向工程导出的xml与接口。

  当然了mybatisplus之后逆向工程导出的mapper继承BaseMapper就完全可以进行单表的增删改查了。也就是没有原来的mybatis逆向工程生成的xml中的SQL。原来mybatis进行单表条件查询的时候是通过XXXExample.Criteria的方式进行查询的。MP是通过Wrapper进行封装查询条件的,而且MP支持好多批量操作,有点类似HibernateTemplate。