MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。官网:https://mybatis.plus/ 或 https://mp.baomidou.com/1.2
文档地址:https://mybatis.plus/guide/
源码地址:https://github.com/baomidou/mybatis-plus
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E7PAikBU-1630307111968)(C:\Users\ASUS\AppData\Local\Temp\1630224549533.png)]
愿景:
我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hX8UIq9F-1630307111971)(C:\Users\ASUS\AppData\Local\Temp\1630224617060.png)]
Mybatis-Plus是由baomidou(苞米豆)组织开发并且开源的,目前该组织大概有16人左右。
码云地址:https://gitee.com/organizations/baomidou
# 创建数据库
create database mp
# 使用数据库
use mp
# 创建测试表
create table tb_user (
id bigint(20) primary key auto_increment comment '主键ID',
user_name varchar(20) not null comment '用户名',
password varchar(20) not null comment '密码',
name varchar(30) default null comment '姓名',
age int(11) default null comment '年龄',
email varchar(50) default null comment '邮箱'
)charset utf8;
# 插入测试数据
insert into tb_user values
('1', 'zhangsan', '123456', '张三', '18', '[email protected]'),
('2', 'lisi', '123456', '李四', '20', '[email protected]'),
('3', 'wangwu', '123456', '王五', '28', '[email protected]'),
('4', 'zhaoliu', '123456', '赵六', '21', '[email protected]'),
('5', 'sunqi', '123456', '孙七', '24', '[email protected]');
# 查询表
select * from tb_user
创建一个mvaen项目 导入相关依赖
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.ziyuangroupId>
<artifactId>mybatis-plusartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>ziyuan.mpmodule>
modules>
<dependencies>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plusartifactId>
<version>3.1.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.26version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.12version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.20version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.21version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
plugins>
build>
project>
通过Mybatis与MyBatis-Plus整合
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis-plusartifactId>
<groupId>org.ziyuangroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>mybatisPlusartifactId>
project>
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
- 编写Mybatis-config.xml 文件
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
mappers>
configuration>
- 编写User实体对象
package pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
- 编写UserDao接口
package dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import pojo.User;
import java.util.List;
public interface UserDao{
List<User> findAll();
}
- 编写UserMapper.xml文件
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.UserDao">
<select id="findAll" resultType="pojo.User">
select * from tb_user
select>
mapper>
- 编写MyTest测试类
package org.ziyuan;
import dao.UserDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import pojo.User;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyTest {
/**
* 原生MyBatis测试
* @throws IOException
*/
@Test
public void test01() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
for (User user : mapper.findAll()) {
System.out.println(user);
}
sqlSession.close();
}
}
- 测试接口
User(id=1, userName=null, password=123456, name=张三, age=18, email=test1@itcast.cn)
User(id=2, userName=null, password=123456, name=李四, age=20, email=test2@itcast.cn)
User(id=3, userName=null, password=123456, name=王五, age=28, email=test3@itcast.cn)
User(id=4, userName=null, password=123456, name=赵六, age=21, email=test4@itcast.cn)
User(id=5, userName=null, password=123456, name=孙七, age=24, email=test5@itcast.cn)
- 在User对象中添加@TableName,指定数据库表名
package pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
- 将UserMapper继承BaseMapper, 拥有BaseMapper中的所有方法
package dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import pojo.User;
import java.util.List;
public interface UserDao extends BaseMapper<User> {
List<User> findAll();
}
- 使用MP中的MybatisSqlSessionFactoryBuilder进行构建
package org.ziyuan;
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
import dao.UserDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import pojo.User;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyTest {
/**
* 原生MyBatisPlus测试
* @throws IOException
*/
@Test
public void test02() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用MybatisSqlSessionFactoryBuilder
SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
// 调用MyBatis-plus方法
List<User> users = mapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
- 测试接口
User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)
User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)
User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@itcast.cn)
User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)
User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@itcast.cn)
由于使用了MybatisSqlSessionFactoryBuilder进行了构建,继承的BaseMapper中的方法就载入到了
SqlSession中,所以就可以直接使用相关的方法;
引入了Spring框架,数据源、构建等工作就交给了Spring管理
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis-plusartifactId>
<groupId>org.ziyuangroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>mybatisPlus-SpringartifactId>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.6version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.3.6version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.3.6version>
dependency>
dependencies>
project>
- 编写jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mp?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTImeBehavior=convertToNull
jdbc.username=root
jdbc.password=root
- 编写applicationContext.xml
<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
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
<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}"/>
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
bean>
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="dao"/>
bean>
beans>
- 编写User对象以及UserDao接口
package pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
package dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import pojo.User;
public interface UserDao extends BaseMapper<User> {}
- 测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MyTest {
@Autowired
private UserDao userDao;
@Test
public void test01(){
for (User user : userDao.selectList(null)) {
System.out.println(user);
}
}
}
User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)
User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)
User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@itcast.cn)
User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)
User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@itcast.cn)
使用SpringBoot将进一步的简化MybatisPlus的整合,需要注意的是
依赖 通过springboot勾选 lombok jdbk mysql创建 添加mybatisPlus-starter 依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.5-SNAPSHOTversion>
<relativePath/>
parent>
<groupId>org.ziyuangroupId>
<artifactId>springboot-mybatisplusartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springboot-mybatisplusname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.1.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
<repositories>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
<repository>
<id>spring-snapshotsid>
<name>Spring Snapshotsname>
<url>https://repo.spring.io/snapshoturl>
<releases>
<enabled>falseenabled>
releases>
repository>
repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
pluginRepository>
<pluginRepository>
<id>spring-snapshotsid>
<name>Spring Snapshotsname>
<url>https://repo.spring.io/snapshoturl>
<releases>
<enabled>falseenabled>
releases>
pluginRepository>
pluginRepositories>
project>
- 编写application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8
username: root
password: root
- 编写User对象以及UserDao接口
package pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
package dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import pojo.User;
public interface UserDao extends BaseMapper<User> {}
- 在启动上 设置接口的扫描包
package org.ziyuan;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("org.ziyuan.dao")
@SpringBootApplication
public class SpringbootMybatisplusApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootMybatisplusApplication.class, args);
}
}
- 测试用例
package org.ziyuan;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.ziyuan.dao.UserDao;
import org.ziyuan.pojo.User;
@SpringBootTest
class SpringbootMybatisplusApplicationTests {
@Autowired
private UserDao userDao;
@Test
void contextLoads() {
for (User user : userDao.selectList(null)) {
System.out.println(user);
}
}
}
User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)
User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)
User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@itcast.cn)
User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)
User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@itcast.cn)
通过继承BaseMapper就可以获取各种各样的单表操作,接下来我们来学习这些操作
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
package org.ziyuan.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
// 指定id类型为自增长
@TableId(type = IdType.AUTO)
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
/**
* 生成ID类型枚举类
*
* @author hubin
* @since 2015-11-10
*/
@Getter
public enum IdType {
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* 该类型可以通过自己注册自动填充插件进行填充
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private final int key;
IdType(int key) {
this.key = key;
}
}
package org.ziyuan;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.ziyuan.dao.UserDao;
import org.ziyuan.pojo.User;
@SpringBootTest
class SpringbootMybatisplusApplicationTests {
@Autowired
private UserDao userDao;
/**
* 插入
*/
@Test
public void testInsert(){
User user = new User();
user.setUserName("ziyuan");
user.setPassword("123456");
user.setName("孙梓源");
user.setAge(0);
user.setEmail("[email protected]");
int insert = userDao.insert(user);
System.out.println(user);
}
}
User(id=6, userName=ziyuan, password=123456, name=孙梓源, age=0, email=ziyuan710@gmail.com)
在MybatisPlus中通过@TableField注解可以指定字段的一些属性,常常解决的问题有3个:
- 对象中的属性名和字段名不一致的问题(非驼峰) @TableField(value = “email”)
- 对象中的属性字段在表中不存在的问题 @TableField(exist = false)
- 不想查询数据库中的某个字段的问题 @TableField(select = false)
package org.ziyuan.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
@TableId(type = IdType.AUTO) // 指定id类型为自增长
private Long id;
@TableField(select = false) // 该字段不加入查询字段
private String password;
@TableField(value = "email") // 解决字段名不一致
private String mail;
@TableField(exist = false) // 该字段数据表中不存在
private String address;
private String userName;
private String name;
private Integer age;
}
在MybatisPlus中,更新操作有2种,一种是根据id更新,另一种是根据条件更新
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 通过Id更新
*/
@Test
public void testUpdate(){
User user = new User();
user.setId(1L);
user.setUserName("sunziyuan");
user.setAge(20);
//根据id更新,更新不为null的字段
userDao.updateById(user);
}
/**
* 通过条件更新 QueryWrapper
*/
@Test
public void testUpdate1(){
User user = new User();
user.setUserName("admin");
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id",1);
// 执行更新
userDao.update(user,wrapper);
}
/**
* 通过条件更新 UpdateWrapper
*/
@Test
public void testUpdate2(){
// 更新的条件
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.set("user_name","admin").set("age",20).eq("id",6);
// 执行更新操作
int update = userDao.update(null, userUpdateWrapper);
System.out.println(update);
}
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 通过Id进行删除
*/
@Test
public void testDelete01(){
int i = userDao.deleteById(7L);
System.out.println("受影响行数:"+i);
}
/**
* 通过Map条件进行删除
*/
@Test
public void testDelete02(){
// 条件
Map<String,Object> map = new HashMap<>();
map.put("id",10L);
// 执行SQL
int i = userDao.deleteByMap(map);
System.out.println("受影响行数:"+i);
}
/**
* 按照条件删除
*/
@Test
public void testDelete03(){
User user = new User();
user.setId(6L);
// 将实体类对象进行封装,封装为操作条件
QueryWrapper<User> wrapper = new QueryWrapper<>(user);
int delete = userDao.delete(wrapper);
System.out.println("受影响行数:"+delete);
}
/**
* 批量删除
*/
@Test
public void testDelete04(){
int i = userDao.deleteBatchIds(Arrays.asList(8L, 9L, 10L));
System.out.println("受影响行数:"+i);
}
MyBatisPlus提供了多种查询操作
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* 注意: 只返回第一个字段的值
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 ID 查询
*/
@Test
public void testQueryId(){
System.out.println(userDao.selectById(1L));
}
/**
* 查询(根据ID 批量查询)
*/
@Test
public void selectBatchIds(){
for (User user : userDao.selectBatchIds(Arrays.asList(1L, 2L, 3L, 4L, 5L))) {
System.out.println(user);
}
}
/**
* 查询(根据 columnMap 条件)
*/
@Test
public void selectByMap(){
// 条件
Map<String, Object> map = new HashMap<>();
map.put("user_name","sunziyuan");
map.put("age",20);
// 执行SQL
for (User user : userDao.selectByMap(map)) {
System.out.println(user);
}
}
/**
* 根据 entity 条件,查询一条记录 封装条件
*/
@Test
public void selectOne(){
// 封装条件
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id",1L);
// 输出
System.out.println(userDao.selectOne(wrapper));
}
/**
* 根据 entity 条件,查询一条记录 封装实体类
*/
@Test
public void selectOne(){
User user = new User();
user.setId(1L);
// 封装条件
QueryWrapper<User> wrapper = new QueryWrapper<>(user);
// 输出
System.out.println(userDao.selectOne(wrapper));
}
/**
* 根据 Wrapper 条件,查询总记录数
*/
@Test
public void selectCount(){
// 封装条件
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",20);
// 输出
System.out.println(userDao.selectOne(wrapper));
}
/**
* 根据 Wrapper 条件,查询总记录数
*/
@Test
public void selectCount(){
// 封装条件
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 查询年龄大于20岁的总人数
wrapper.gt("age",20);
// 输出
System.out.println(userDao.selectCount(wrapper));
}
/**
* 根据 entity 条件,查询全部记录
*/
@Test
void selectList() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",20);
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}
/**
* 根据 Wrapper 条件,只返回第一个字段的值
*/
@Test
public void selectObjs(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",20);
System.out.println(userDao.selectObjs(wrapper));
}
/**
* 配置分页插件
*/
@MapperScan("org.ziyuan.dao")
@Configuration
public class MyBatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
/**
* 根据 entity 条件,查询全部记录(并翻页)
*/
@Test
public void selectPage(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",20);
Page<User> page = new Page<>(1, 1);
// 根据条件查询数据
IPage<User> userIPage = userDao.selectPage(page, wrapper);
System.out.println("数据总条数:"+userIPage.getTotal());
System.out.println("总页数:"+userIPage.getPages());
// 获取数据
List<User> users = userIPage.getRecords();
for (User user : users) {
System.out.println(user);
}
}
/**
* 根据 entity 条件,查询全部记录(并翻页)
*/
@Test
public void selectMapsPage(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",20);
Page<User> page = new Page<>(1, 1);
// 根据条件查询数据
IPage<Map<String, Object>> userIPage = userDao.selectMapsPage(page, wrapper);
System.out.println("数据总条数:"+userIPage.getTotal());
System.out.println("总页数:"+userIPage.getPages());
// 获取数据
List<Map<String, Object>> records = userIPage.getRecords();
records.stream().forEach(System.out::println);
}
前面我们已经知道,MybatisPlus在启动后会将BaseMapper中的一系列的方法注册到mappedStatements中,那么究竟是如何注入的呢?流程又是怎么样的?
在MybatisPlus 中,ISqlInjector负责SQL的注入工作,它是一个接口,actSqlInjector是它的实现类,实现关系如下:
在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:
@Override
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
Class<?> modelClass = extractModelClass(mapperClass);
if (modelClass != null) {
String className = mapperClass.toString();
Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
if (!mapperRegistryCache.contains(className)) {
List<AbstractMethod> methodList = this.getMethodList();
if (CollectionUtils.isNotEmpty(methodList)) {
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
// 循环注入自定义方法
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
} else {
logger.debug(mapperClass.toString() + ", No effective injection method was found.");
}
mapperRegistryCache.add(className);
}
}
}
在实现方法中,
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
是关键,循环遍历方法,进行注入最终调用抽象方法injectMappedStatement进行真正的注入:
/**
* 注入自定义 MappedStatement
*
* @param mapperClass mapper 接口
* @param modelClass mapper 泛型
* @param tableInfo 数据库表反射信息
* @return MappedStatement
*/
public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo);
查看该方法的实现:
以SelectById为例查看:
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID;
SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(),
sqlSelectColumns(tableInfo, false),
tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
tableInfo.getLogicDeleteSql(true, false)), Object.class);
return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, tableInfo);
}
可以看到,生成了SqlSource对象,再将SQL通过addSelectMappedStatement方法添加到meppedStatements中
在MybatisPlus中有大量的配置,其中有一部分是Mybatis原生的配置,另一部分是MybatisPlus的配置
官方文档: https://mp.baomidou.com/guide/config.html
MyBatis 配置文件位置,如果您有单独的 MyBatis 配置,请将其路径配置到 configLocation 中。 MyBatis
Configuration 的具体内容请参考MyBatis 官方文档
# SpringBoot yaml 配置方式
mybatis-plus:
config-location: classpath:mybatis-config.xml
# Spring MVC xml 配置方式
>
:mybatis-config.xml"/>
>
MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行
该配置,告诉 Mapper 所对应的 XML 文件位置。
# springBoot配置
mybatis-plus:
mapper-locations: classpath*:mybatis/*.xml
# SpringMVC配置
>
*:mybatis/*.xml"/>
>
MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使
用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名)。
# SpringBoot 配置
mybatis-plus:
type-aliases-package: pojo
# SpringMvc 配置
>
>
>
部分(Configuration)的配置大都为 MyBatis 原生支持的配置,这意味着您可以通过 MyBatis XML 配置文件的形
式进行配置。
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属
性名 aColumn(驼峰命名) 的类似映射。
#关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
# 类型: boolean
# 默认值: true
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true。
# 缓存策略
# 类型: boolean
# 默认值: true
mybatis-plus:
configuration:
cache-enabled: false
全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置。
# SpringBoot 配置
# 类型: com.baomidou.mybatisplus.annotation.IdType
# 默认值: ID_WORKER
mybatis-plus:
global-config:
db-config:
id-type: auto
# SpringMVC 配置
<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
>
>
>
>
>
>
>
>
>
>
>
>
表名前缀,全局配置后可省略@TableName()配置。
# SpringBoot 配置
# 类型: String
# 默认值: null
mybatis-plus:
global-config:
db-config:
table-prefix: tb_
# SpringMVC 配置
>
>
>
>
>
>
>
>
>
>
>
>
>
官方文档: https://mp.baomidou.com/guide/wrapper.html
在MybatisPlus中,Wrapper接口的实现类关系如下:
可以看到,AbstractWrapper和AbstractChainWrapper是重点实现,接下来我们重点学习AbstractWrapper以及其
子类。QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类 用于生成 sql
的 where 条件, entity 属性也用于生成 sql 的 where 条件 注意: entity 生成的 where 条件与 使用各个 api 生成
的 where 条件没有任何关联行为
全部eq(或个别isNull)
个别参数说明: 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(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
个别参数说明: filter : 过滤函数,是否允许字段传入比对条件中
params 与 null2IsNull: 同上 例1: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:“老王”,age:null}) —> name = ‘老王’ and age is null
例2: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:“老王”,age:null}, false) —> 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)
@Test
public void testWrapper(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//设置条件
Map<String,Object> params = new HashMap<>();
params.put("user_name","lisi");
params.put("age",20);
params.put("password",null);
// SELECT * FROM tb_user WHERE password IS NULL AND name = ? AND age = ?
//wrapper.allEq(params);
// SELECT * FROM tb_user WHERE name = ? AND age = ?
//wrapper.allEq(params,false);
// SELECT * FROM tb_user WHERE name = ? AND age = ?
wrapper.allEq((k,v)->k.equals("user_name") || k.equals("age"),params);
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}
eq 等于 =
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
between between 值1 and 值2
notBetween not between 值1 and 值2
in 字段 in(1,2,3)
notIn 字段 notIn(1,2,3)
/**
* 基本比较操作
*/
public void testEquals(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("password","123456")
.ge("age",20)
.in("name","张三","李四","王五");
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}
like like(“name”,“王”) ----> name like “%王%”
notLike notLike(“name”,“王”) ----> name not like “%王%”
likeLeft likeLeft(“name”,“王”) ----> name like “%王”
likeRight likeRight(“name”,“王”) ----> name like “王%”
/**
* 模糊查询
*/
@Test
public void testLike(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name","张");
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}
orderBy order by(true,true,“id”,“name”) -----> order by id asc,name asc
orderByAsc order by(“id”,“name”) -----> order by id asc,name asc
orderByDesc order by(“id”,“name”) -----> order by id desc,name desc
/**
* 排序
*/
@Test
public void testOrder(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("age");
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}
or 拼接or 主动调用or 表示紧接着下一个方法不是用and 连接!(不调用or 则默认为使用and 连接)
and 拼接and and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> and (name = ‘李白’ and status<> ‘活着’)
/**
* 逻辑查询
*/
@Test
public void testOrAnd(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","李四").or().eq("age",24);
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}
在MybatisPlus中,默认查询所有的字段,如果只需要某写字段可以使用select指定字段
/**
* 字段查询
*/
@Test
public void testSelect(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id","name");
for (User user : userDao.selectList(wrapper)) {
System.out.println(user);
}
}