简介
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatis-Plus官网地址https://www.mybatis-plus.com/
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
支持数据库
任何能使用Mybatis进行CRUD,并且支持标准SQL的数据库,MP都是支持的。具体支持的数据库如下:
- MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
- 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库
集成MP
准备工作:
创建测试用的数据库以及测试数据
-- 创建测试表
DROP TABLE IF EXISTS tb_user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
-- 插入测试数据
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');
方式一:mybatis+mybatis-plus
- 新建项目,引入对应依赖
<dependencies>
<!-- mybatis-plus插件依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.1.1</version>
</dependency>
<!--Mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.11</version>
</dependency>
<!--简化bean代码的工具包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
编写配置文件
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mp?serverTimezone=GMT%2B8&useSSL=false
jdbc.username=root
jdbc.password=admin
log4j.properties
log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
sqlMapConfig.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>
<properties resource="jdbc.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/zql/mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
- 编写对应实体类以及mapper
user.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
userMapper.java
public interface UserMapper extends BaseMapper<User> {
List<User> findAll();
}
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.zql.mapper.UserMapper">
<select id="findAll" resultType="com.zql.pojo.User">
select * from user
</select>
</mapper>
- 使用Mybatis与Mybatis-Plus测试对比
Mybatis中使用自定义查询方式测试
@Test
public void test1() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapconfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 自定义的查询接口
List<User> users = mapper.findAll();
users.forEach(System.out::println);
}
Mybaits-Plus中查询的方法测试
@Test
public void test2() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sqlMapconfig.xml");
// 使用MP是将MyBatis的SqlSessionFactoryBuilder换成MP的MybatisSqlSessionFactoryBuilder,同时mapper继承BaseMapper
SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 使用MP中查询所有的方法
List<User> users = mapper.selectList(null);
users.forEach(System.out::println);
}
总结:使用MP是对应的mapper和service应继承BaseMapper和BaseService接口,因为父类中已有很多方法,所以无需编写对应语句,可以直接使用父类中的方法,同时MyBatis集成MP时应注意:将Mybatis的SqlSessionFactoryBuilder换成MyBatisSqlSessionFactoryBuilder
MP中提供了大量的方法供我们使用
方式二:spring+Mybatis+Mybatis-Plus
- 创建项目,提价对应依赖
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring.version>5.1.6.RELEASE</spring.version>
</properties>
<dependencies>
<!-- mybatis-plus插件依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.1.1</version>
</dependency>
<!--Mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.11</version>
</dependency>
<!--简化bean代码的工具包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
- 编写对应配置文件
applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--引入properties-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--dataSource-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--这里使用MP提供的sqlSessionFactory,完成spring与mp的整合-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--扫描mapper接口,使用的依然是mybatis原生的扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zql.mapper"></property>
</bean>
</beans>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mp?serverTimezone=GMT%2B8&useSSL=false
jdbc.username=root
jdbc.password=admin
log4j.properties
log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
- 编写对应实体类以及Mapper
user.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
userMapper.java
@Mapper
public interface UserMapper extends BaseMapper<User> {
List<User> findAll();
}
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.zql.mapper.UserMapper">
<select id="findAll" resultType="com.zql.pojo.User">
select * from user
</select>
</mapper>
- 编写测试类进行测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class MPTest {
@Autowired
private UserMapper userMapper;
@Test
public void test1() throws IOException {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
方式三:SpringBoot集成Mybatis-Plus
- 创建SpringBoot项目并引入Mybatis-Plus的maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--简化代码的工具包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis-plus的springboot支持-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
- 在启动类上配置 MapperScan 注解
@MapperScan("com.zql.mapper")
@SpringBootApplication
public class ZqlSpringbootMpApplication {
public static void main(String[] args) {
SpringApplication.run(ZqlSpringbootMpApplication.class, args);
}
}
- 在
application.yml
配置文件中添加数据库的相关配置:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mp?serverTimezone=GMT%2B8&useSSL=false
username: root
password: admin
- 编写实体类
User.java
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
/**
* value : 数据库字段名 (可解决字段与数据库列名不一致问题)
* exist : 是否为数据库表字段 (当数据库中字段没有这一属性是可以设置为false)
* select : 是否进行 select 查询 (select查询是是否查询出此值)
* ...
*/
@TableField(value = "name",exist = true,select = false)
private String name;
private Integer age;
private String email;
private Long size;
}
- 编写 Mapper 包下的
UserMapper
接口
public interface UserMapper extends BaseMapper<User> {
}
- 添加测试类,进行功能测试:
@SpringBootTest
class ZqlSpringbootMpApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
}
通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用遍写!
从以上步骤中,我们可以看到集成MyBatis-Plus
非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。
但 MyBatis-Plus 的强大远不止这些功能,spring整合Mybatis-plus请查看官网Spring MVC启动示例 MP官方Spring MVC启动示例
注解
@TableName
- 描述:表名注解,标识实体类对应的表
- 使用位置:实体类
示例
@TableName("sys_user")
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
@TableId
- 描述:主键注解
- 使用位置:实体类主键字段
示例
@TableName("sys_user")
public class User {
/**
* value : 主键字段名
* type : 指定主键类型
* AUTO : 数据库 ID 自增
* NONE : 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
* INPUT : insert 前自行 set 主键值
* ASSIGN_ID : 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since
* 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为
* DefaultIdentifierGenerator雪花算法)
* ASSIGN_UUID :分配 UUID,主键类型为 String(since 3.3.0),使用接口
* IdentifierGenerator的方法nextUUID(默认 default 方法)
**/
@TableId(value="id",type="IdType.AUTO")
private Long id;
private String name;
private Integer age;
private String email;
}
@TableFieId
- 描述:字段注解(非主键)
/**
* value : 数据库字段名 (可解决字段与数据库列名不一致问题)
* exist : 是否为数据库表字段 (当数据库中字段没有这一属性是可以设置为false)
* select : 是否进行 select 查询 (select查询是是否查询出此值)
* ...
*/
@TableField(value = "name",exist = true,select = false)
private String name;
@Version
- 描述:乐观锁注解、标记
@Verison
在字段上
@KeySequence
- 描述:序列主键策略
oracle
- 属性:value、resultMap
@OrderBy
- 描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
CRUD接口
Mybatis-Plus中的CRUD接口分为service CRUD接口和Mapper CRUD接口
Service CRUD接口
说明:
- 通用 Service CRUD 封装IService (opens new window)接口,进一步封装 CRUD 采用
get 查询单行
remove 删除
list 查询集合
page 分页
前缀命名方式区分Mapper
层避免混淆,- 泛型
T
为任意实体对象- 建议如果存在自定义通用 Service 方法的可能,请创建自己的
IBaseService
继承Mybatis-Plus
提供的基类- 对象
Wrapper
为 条件构造器
Save
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Collection<T> | entityList | 实体对象集合 |
int | batchSize | 插入批次数量 |
SaveOrUpdate
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
Remove
// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
Update
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);
Get
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
List
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
Page
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
Count
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
Chain
query
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();
update
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);
Mapper CRUD 接口
说明:
- 通用 CRUD 封装BaseMapper (opens new window)接口,为
Mybatis-Plus
启动时自动解析实体表关系映射转换为Mybatis
内部对象注入容器- 泛型
T
为任意实体对象- 参数
Serializable
为任意类型主键Mybatis-Plus
不推荐使用复合主键约定每一张表都有自己的唯一id
主键- 对象
Wrapper
为 条件构造器
Insert
// 插入一条记录
int insert(T entity);
Delete
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
Update
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);
Select
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
条件构造器
allEq
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
params
:key
为数据库字段名,value
为字段值null2IsNull
: 为true
则在map
的value
为null
时调用 isNull 方法,为false
时则忽略value
为null
的
- 例1:
allEq({id:1,name:"老王",age:null})
--->id = 1 and name = '老王' and age is null
- 例2:
allEq({id:1,name:"老王",age:null}, false)
--->id = 1 and name = '老王'
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
filter
: 过滤函数,是否允许字段传入比对条件中
params
与null2IsNull
: 同上
eq
eq(R column, Object val)
eq(boolean condition, R column, Object val)
- 等于 =
- 例:
eq("name", "老王")
--->name = '老王'
ne
ne(R column, Object val)
ne(boolean condition, R column, Object val)
- 不等于 <>
- 例:
ne("name", "老王")
--->name <> '老王'
gt
gt(R column, Object val)
gt(boolean condition, R column, Object val)
- 大于 >
- 例:
gt("age", 18)
--->age > 18
ge
ge(R column, Object val)
ge(boolean condition, R column, Object val)
- 大于等于 >=
- 例:
ge("age", 18)
--->age >= 18
lt
lt(R column, Object val)
lt(boolean condition, R column, Object val)
- 小于 <
- 例:
lt("age", 18)
--->age < 18
le
le(R column, Object val)
le(boolean condition, R column, Object val)
- 小于等于 <=
- 例:
le("age", 18)
--->age <= 18
between
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
- BETWEEN 值1 AND 值2
- 例:
between("age", 18, 30)
--->age between 18 and 30
notBetween
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
- NOT BETWEEN 值1 AND 值2
- 例:
notBetween("age", 18, 30)
--->age not between 18 and 30
like
like(R column, Object val)
like(boolean condition, R column, Object val)
- LIKE '%值%'
- 例:
like("name", "王")
--->name like '%王%'
notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
- NOT LIKE '%值%'
- 例:
notLike("name", "王")
--->name not like '%王%'
likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
- LIKE '%值'
- 例:
likeLeft("name", "王")
--->name like '%王'
likeRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
- LIKE '值%'
- 例:
likeRight("name", "王")
--->name like '王%'
isNull
isNull(R column)
isNull(boolean condition, R column)
字段 IS NULL
例: isNull("name")--->name is null
isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)
- 字段 IS NOT NULL
- 例:
isNotNull("name")
--->name is not null
in
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
- 字段 IN (value.get(0), value.get(1), ...)
- 例:
in("age",{1,2,3})
--->age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)
- 字段 IN (v0, v1, ...)
- 例:
in("age", 1, 2, 3)
--->age in (1,2,3)
notIn
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
- 字段 NOT IN (value.get(0), value.get(1), ...)
- 例:
notIn("age",{1,2,3})
--->age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
- 字段 NOT IN (v0, v1, ...)
- 例:
notIn("age", 1, 2, 3)
--->age not in (1,2,3)
inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
字段 IN ( sql语句 )
例: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)
例: inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)
notInSql
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
字段 NOT IN ( sql语句 )
例: notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6)
例: notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3)
groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)
- 分组:GROUP BY 字段, ...
- 例:
groupBy("id", "name")
--->group by id,name
orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
- 排序:ORDER BY 字段, ... ASC
- 例:
orderByAsc("id", "name")
--->order by id ASC,name ASC
orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
- 排序:ORDER BY 字段, ... DESC
- 例:
orderByDesc("id", "name")
--->order by id DESC,name DESC
orderBy
orderBy(boolean condition, boolean isAsc, R... columns)
- 排序:ORDER BY 字段, ...
- 例:
orderBy(true, true, "id", "name")
--->order by id ASC,name ASC
having
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
- HAVING ( sql语句 )
- 例:
having("sum(age) > 10")
--->having sum(age) > 10
- 例:
having("sum(age) > {0}", 11)
--->having sum(age) > 11
func
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
- func 方法(主要方便在出现if...else下调用不同方法能不断链)
- 例:
func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})
or
or()
or(boolean condition)
注意事项:
主动调用
or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接
- 例:
eq("id",1).or().eq("name","老王")
--->id = 1 or name = '老王'
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
- OR 嵌套
- 例:
or(i -> i.eq("name", "李白").ne("status", "活着"))
--->or (name = '李白' and status <> '活着')
and
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
- AND 嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))
--->and (name = '李白' and status <> '活着')
nested
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
- 正常嵌套 不带 AND 或者 OR
- 例:
nested(i -> i.eq("name", "李白").ne("status", "活着"))
--->(name = '李白' and status <> '活着')
apply
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
注意事项:
该方法可用于数据库函数 动态入参的
params
对应前面applySql
内部的{index}
部分.这样是不会有sql注入风险的,反之会有!
- 例:
apply("id = 1")
--->id = 1
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")
--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last
last(String lastSql)
last(boolean condition, String lastSql)
注意事项:
只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
- 例:
last("limit 1")
exists
exists(String existsSql)
exists(boolean condition, String existsSql)
- 拼接 EXISTS ( sql语句 )
- 例:
exists("select id from table where age = 1")
--->exists (select id from table where age = 1)
notExists
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
- 拼接 NOT EXISTS ( sql语句 )
- 例:
notExists("select id from table where age = 1")
--->not exists (select id from table where age = 1)
QueryWrapper
说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取
select
select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
说明:
以上方法分为两类.
第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper
内的entity
属性有值! 这两类方法重复调用以最后一次为准
- 例:
select("id", "name", "age")
- 例:
select(i -> i.getProperty().startsWith("test"))
UpdateWrapper
说明:
继承自
AbstractWrapper
,自身的内部属性entity
也用于生成 where 条件
及LambdaUpdateWrapper
, 可以通过new UpdateWrapper().lambda()
方法获取!
set
set(String column, Object val)
set(boolean condition, String column, Object val)
- SQL SET 字段
- 例:
set("name", "老李头")
- 例:
set("name", "")
--->数据库字段值变为空字符串 - 例:
set("name", null)
--->数据库字段值变为null
setSql
setSql(String sql)
- 设置 SET 部分 SQL
- 例:
setSql("name = '老李头'")
lambda
- 获取
LambdaWrapper
在QueryWrapper
中是获取LambdaQueryWrapper
在UpdateWrapper
中是获取LambdaUpdateWrapper
插件
MybatisPlusInterceptor
该插件是核心插件,目前代理了 Executor#query
和 Executor#update
和StatementHandler#prepare
方法
目前已有的功能:
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
分页插件
Springboot使用MyBatis-Plus插件的方式只需要增加其配置即可
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
编写测试类
@Test
public void testPage() {
IPage<User> page = new Page<>(1, 2);
IPage<User> userPage = userMapper.selectPage(page, null);
List<User> users = userPage.getRecords();
users.forEach(System.out::println);
System.out.println(userPage.getSize());
System.out.println(userPage.getTotal());
System.out.println(userPage.getPages());
System.out.println(userPage.getCurrent());
}
效果查看
性能分析插件
/**
* 性能分析插件
* @return
*/
@Bean
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
// 设置SQL语句最大执行时间
performanceInterceptor.setMaxTime(100L);
// 设置SQL语句是否格式化显示
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
乐观锁插件
OptimisticLockerInnerInterceptor
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
使用乐观锁插件需要在实体类的字段上加上@Version
注解
@Version
private Integer version;
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1
newVersion
会回写到entity
中- 仅支持
updateById(id)
与update(entity, wrapper)
方法- 在
update(entity, wrapper)
方法下,wrapper
不能复用!!!
spring使用MyBatis-Plus插件方式请查看官网
代码生成器
注意
适用版本:mybatis-plus-generator 3.5.1 以下版本,3.5.1 及以上的请参考 代码生成器新
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
代码示例:
package com.zql;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* <p>
* mysql 代码生成器演示例子
* </p>
*/
public class CodeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
/**
* RUN THIS
*/
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
final String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("zql");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("admin");
mpg.setDataSource(dsc);
// 包配置
final PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模块名"));
pc.setParent("com.zql");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
return projectPath + "/zql-springboot-mp/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseEntity");
strategy.setEntityLombokModel(true);
// strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");
strategy.setInclude(scanner("表名"));
strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
// 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
演示效果
MybatisX快速开发插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:
打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx
搜索并安装。
功能:
- XML 跳转
- 生成代码(需先在 idea 配置 Database 配置数据源)
- 重置模板
- JPA 提示
安装后效果
具体操作就不做演示了,赶紧用起来吧!用过的都说好。嘻嘻