Mybatis Plus简介
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis
的基础上只做增强不做改变,避免了我们重复CRUD语句。
搭建使用环境(SpringBoot)
1.创建一个简单点的maven工程
2.在pom.xml中引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<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><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.RELEASE</version><relativePath/></parent><modelVersion>4.0.0</modelVersion><artifactId>MybatisPlusDemo</artifactId><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><mybatisplus.version>3.3.2</mybatisplus.version><skipTests>true</skipTests></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatisplus.version}</version></dependency><dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.11</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
3.在资源目录下创建application.yml配置文件和目录
在application.yml中写上数据库的配置和Mybatis扫描
# DataSource Config
spring:datasource:driver-class-name: org.h2.Driverschema: classpath:db/schema-h2.sqldata: classpath:db/data-h2.sqlurl: jdbc:h2:mem:testusername: rootpassword: test
# Logger Config
logging:level:com.da: debug# 配置mybatis plus
mybatis-plus:type-aliases-package: com.da.domain #别名搜索mapper-locations: classpath:/mapper/*.xml #加载映射文件
3.1 yml配置简介
在Springboot中,推荐使用properties或者YAML文件来完成配置,但是对于较复杂的数据结构来说,YAML又远远优于properties。
先来看一个Springboot中的properties文件和对应YAML文件的对比:
#properties:
server.port=8090
logging.level.com.xls=debug
spring.thymeleaf.cache=false
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot
spring.datasource.username=root
spring.datasource.password=da5201314
# 可省略,SpringBoot自动推断
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.minimum-idle=10# mybatis 别名扫描
mybatis.type-aliases-package=com.xls.domain
# mapper.xml文件位置,如果没有映射文件,请注释掉
mybatis.mapper-locations=classpath:mappers/*.xml
#YAML格式
# DataSource Config
spring:datasource:driver-class-name: org.h2.Driverschema: classpath:db/schema-h2.sqldata: classpath:db/data-h2.sqlurl: jdbc:h2:mem:testusername: rootpassword: test
# Logger Config
logging:level:com.da: debug# 配置mybatis plus
mybatis-plus:type-aliases-package: com.da.domain #别名搜索mapper-locations: classpath:/mapper/*.xml #加载映射文件
可以明显的看到,在处理层级关系的时候,properties需要使用大量的路径来描述层级(或者属性),比如environments.dev.url和environments.dev.name。其次,对于较为复杂的结构,比如数组(my.servers),写起
来更为复杂。而对应的YAML格式文件就简单很多
3.2 在db目录下创建两个sql数据库脚本文件
1.
schema-h2.sql
其内容如下
DROP TABLE IF EXISTS user2;CREATE TABLE user2
(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)
);
data-h2.sql
其内容如下
DELETE FROM user2;INSERT INTO user2 (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, 'kth1', 331, 'test4@baomidou.com'),
(6, 'knv2', 331, 'test4@baomidou.com'),
(7, 'kav', 331, 'test4@baomidou.com'),
(8, 'kssr', 331, 'test4@baomidou.com'),
(9, 'katr', 331, 'test4@baomidou.com'),
(10, 'kgeb', 331, 'test4@baomidou.com'),
(11, 'ka7', 331, 'test4@baomidou.com'),
(12, 'kha8', 331, 'test4@baomidou.com'),
(13, 'koa9', 331, 'test4@baomidou.com'),
(14, 'iloe', 331, 'test4@baomidou.com'),
(15, 'kaili', 331, 'test4@baomidou.com'),
(16, 'kty12', 331, 'test4@baomidou.com'),
(17, 'ka13', 331, 'test4@baomidou.com'),
(18, 'ryr', 331, 'test4@baomidou.com'),
(19, 'wrt31', 757,'test4@baomidou.com'),
(20, 'yr16', 331, 'test4@baomidou.com'),
(21, 'jrr17', 331, 'test4@baomidou.com'),
(22, 'ya18', 331, 'test4@baomidou.com'),
(23, 'tur9', 331, 'test4@baomidou.com'),
(24, 'hak15', 331, 'test4@baomidou.com'),
(25, 'Biie', 24, 'test5@baomidou.com');
h2数据库是一个基于内存的数据库,在jvm启动时,自动执行脚本加载相应的数据
springboot 中使用h2数据库直接按照上面配置,配置schema表结构脚本和data数据脚本即可
注意这里用户名密码可以省略不写,或者随意设定
4.目录结构如下
5.启动类Application
@SpringBootApplication
@MapperScan("com.da.mapper")//开启扫描
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class,args);}
}
5.1 实体类User
import com.baomidou.mybatisplus.annotation.TableName;@TableName("user2")
public class User {private Long id;private String name;private Integer age;private String email;public User() {}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", email='" + email + '\'' +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}
}
5.2 UserMapper
public interface UserMapper extends BaseMapper<User> {
}
5.3 MyBatisPlusTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyBatisPlusTest {@ResourceUserMapper userMapper;@Testpublic void test(){List<User> users = userMapper.selectList(null);users.forEach(user ->{System.out.println(user);});}
}
测试
Mybatis Plus 常用注解
MyBatisPlus提供了一些注解供我们在实体类和表信息出现不对应的时候使用。通过使用注解完成逻辑上匹配。
注解名称 | 说明 |
---|---|
@TableName | 实体类的类名和数据库表名不一致 |
@TableId | 实体类的主键名称和表中主键名称不一致 |
@TableField | 实体类中的成员名称和表中字段名称不一致 |
mybatis plus注解策略配置
如果mysql自增主键注解策略设置如下
@TableId(type = IdType.AUTO) private Long id;
默认主键策略
/**
* 采用雪花算法生成全局唯一主键
**/
ASSIGN_ID(3)
排除实体类中非表字段
使用 @TableField(exist = false)
注解
Mybatis Plus 内置插入方法
@Testpublic void insert(){User user=new User();user.setId(26L);user.setName("我是insert");user.setAge(23);user.setEmail("da@163.com");int insert = userMapper.insert(user);if(insert>0){System.out.println("插入成功!!!");List<User> users = userMapper.selectList(null);users.forEach(user1 -> {System.out.println(user1);});}else{System.out.println("插入失败!!");}}
结果:
Mybatis Plus 内置查询方法
@Testpublic void select(){//查询全部List<User> users = userMapper.selectList(null);users.forEach(user ->{System.out.println(user);});System.out.println("===========================根据条件查询=====================");//根据条件查询List<User> users1 = userMapper.selectList(new QueryWrapper<User>().like("name", "J"));users1.forEach(user ->{System.out.println(user);});//根据条件查询一个System.out.println("===========================根据条件查询一个=====================");User user = userMapper.selectOne(new QueryWrapper<User>().eq("name", "Biie"));System.out.println(user);//根据主键查询System.out.println("===========================根据主键查询一个=====================");User user1 = userMapper.selectById(2);System.out.println(user1);}
结果
Mybatis Plus 内置修改方法
@Testpublic void update(){User user=new User();user.setId(5L);user.setName("我修改后的数据");user.setAge(230);user.setEmail("dada@163.com");//根据id修改System.out.println("根据id修改");userMapper.updateById(user);User user1 = userMapper.selectById(5);System.out.println(user1);System.out.println("=======================根据条件修改方式1===============================");userMapper.update(null, Wrappers.<User>update().set("email","@update.com").like("name","B"));List<User> users = userMapper.selectList(new QueryWrapper<User>().like("name", "B"));users.forEach(user11 -> {System.out.println(user11);});user.setName("根据条件修改方式2");System.out.println("=======================根据条件修改方式2===============================");userMapper.update(user, Wrappers.<User>update().eq("id","5"));List<User> users1 = userMapper.selectList(new QueryWrapper<User>().eq("id", "5"));users1.forEach(user11 -> {System.out.println(user11);});}
结果
Mybatis Plus 内置删除方法
@Test
public void delete(){//根据Id删除int i = userMapper.deleteById(1);
if(i>0){System.out.println("删除成功!!!");userMapper.selectList(null).forEach(user -> {System.out.println(user);});
}//根据条件删除方式1int delete = userMapper.delete(new QueryWrapper<User>().like("name", "J"));
if(delete>0){System.out.println("根据条件删除方式1删除成功");userMapper.selectList(null).forEach(user -> {System.out.println(user);});
}//根据条件删除方式2int delete1 = userMapper.delete(Wrappers.<User>query().like("name", "T"));if(delete1>0){System.out.println("根据条件删除方式2删除成功");userMapper.selectList(null).forEach(user -> {System.out.println(user);});}}
结果
分页
在pom.xml中引入pageHelper分页依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.11</version></dependency>
在config包中新键分页配置类
MybatisPlusConfig
@Configuration
public class MybatisPlusConfig {/*分页插件*/@Beanpublic PaginationInterceptor paginationInterceptor() {
// 开启 count 的 join 优化,只针对 left join !!!return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));}/*** 两个分页插件都配置,不会冲突* pagehelper的分页插件*/@Beanpublic PageInterceptor pageInterceptor() {return new PageInterceptor();}}
Mybatis Plus 内置分页
@Testpublic void page(){System.out.println("----baseMapper自带分页");//第一个参数是当前页,第二参数是每页数Page<User>page=new Page<>(1,5);IPage<User> userPage = userMapper.selectPage(page, new QueryWrapper<User>());System.out.println("当前页码:"+userPage.getCurrent());System.out.println("每页数:"+userPage.getSize());System.out.println("总条数"+userPage.getTotal());//获取分页的结果userPage.getRecords().forEach(user ->{System.out.println(user);});}
结果
自定义xml分页
application.yml配置文件
# 配置mybatis plus
mybatis-plus:type-aliases-package: com.da.domain #别名搜索mapper-locations: classpath:/mapper/*.xml #加载映射文件
UserMapper接口
public interface UserMapper extends BaseMapper<User>{/*** 如果映射的接口方法有2个参数需要@Param定义参数名,定义参数名后,映射文件中使用p.属性 c.属性,具体访问** @param page* @param conditioin* @return*/public IPage<User> selectUserByPage(@Param("p") IPage<User> page, @Param("c") Userconditioin);public List<User>selectUserByPage2(User u);
}
UserMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.da.mapper.UserMapper"><sql id="selectSql">select * from user2</sql><select id="selectUserByPage" resultType="user"><include refid="selectSql"></include><where><if test="c.email !=null">email like '%${c.email}%'</if><if test="c.age !=null">and age = #{c.age}</if></where></select></mapper>
测试
@Testpublic void testPage(){//自定义XML分页查询Page<User>page=new Page<>(1,5);User user=new User();user.setEmail("te");user.setAge(331);IPage<User> userPage = userMapper.selectUserByPage(page, user);System.out.println("当前页码:"+userPage.getCurrent());System.out.println("每页数:"+userPage.getSize());System.out.println("总条数"+userPage.getTotal());//获取分页的结果userPage.getRecords().forEach(user1 ->{System.out.println(user1);});}
结果
pageHelper分页
开启扫描
UserMapper.xml映射文件
<select id="selectUserByPage2" resultType="user"><include refid="selectSql"></include><where><if test="age !=null">age = #{age}</if><if test="email !=null">and email like '%${email}%'</if></where>
</select>
测试
@Testpublic void pageHelper(){//自定义XML分页查询User user=new User();user.setEmail("te");user.setAge(331);PageInfo<User>page= PageHelper.startPage(1,5).doSelectPageInfo(()-> userMapper.selectUserByPage2(user));
/* PageHelper.startPage(1,5);PageInfo<User>page=new PageInfo<>(userMapper.selectUserByPage2(user));*/System.out.println("总行数=" + page.getTotal());System.out.println("当前页=" + page.getPageNum());System.out.println("每页行数=" + page.getPageSize());System.out.println("总页数=" + page.getPages());System.out.println("起始行数=" + page.getStartRow());System.out.println("是第一页=" + page.isIsFirstPage());System.out.println("是最后页=" + page.isIsLastPage());System.out.println("还有下一页=" + page.isHasNextPage());System.out.println("还有上一页=" + page.isHasPreviousPage());System.out.println("页码列表" + Arrays.toString(page.getNavigatepageNums()));page.getList().forEach(System.out::println);}
结果