MyBatis-plus的入门使用
Mybatis-plus架构
作者
快速开始
常用的方式
- MyBatis+MP(Mybatis-plus)
- spring+MyBatis+MP(Mybatis-plus)
- springboot+MyBatis+MP(Mybatis-plus)
创建数据库和表
/**创建数据库*/
create database mp CHARACTER set utf8;
/**使用数据库*/
use mp;
/*创建表*/
CREATE TABLE `tb_user` ( `id` bigint(20) NOT NULL 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 '邮箱',
PRIMARY KEY (`id`) )
ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
--插入数据
INSERT INTO `tb_user` ( `id`, `user_name`, `password`, `name`, `age`, `email` )
VALUES
( '1', 'zhangsan', '123456', '张三', '18', '[email protected]' );
INSERT INTO `tb_user` ( `id`, `user_name`, `password`, `name`, `age`, `email` )
VALUES
( '2', 'lisi', '123456', '李四', '20', '[email protected]' );
INSERT INTO `tb_user` ( `id`, `user_name`, `password`, `name`, `age`, `email` )
VALUES
( '3', 'wangwu', '123456', '王五', '28', '[email protected]' );
INSERT INTO `tb_user` ( `id`, `user_name`, `password`, `name`, `age`, `email` )
VALUES
( '4', 'zhaoliu', '123456', '赵六', '21', '[email protected]' );
INSERT INTO `tb_user` ( `id`, `user_name`, `password`, `name`, `age`, `email` )
VALUES
( '5', 'sunqi', '123456', '孙七', '24', '[email protected]' );
Mybatis + MP
添加jar包依赖
<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>
<optional>true</optional>
<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>
<build>
<plugins>
<plugin>
<!-- 指定Jdk的版本 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
日志配置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实现查询User
编写mybatis-config.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
编写user实现类,使用lombok进行注解
package cn.itcast.mp.simple.pojo;
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;
}
编写UserMapper接口
package cn.itcast.mp.simple.mapper;
import java.util.List;
import cn.itcast.mp.simple.pojo.User;
public interface UserMapper {
public 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="cn.itcast.mp.simple.mapper.UserMapper">
<select id="findAll" resultType="cn.itcast.mp.simple.pojo.User">
select * from tb_user
</select>
</mapper>
编写测试类TestMyBatis
package test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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 cn.itcast.mp.simple.mapper.UserMapper;
import cn.itcast.mp.simple.pojo.User;
public class TestMyBatis {
@Test
public void findAll() throws IOException {
InputStream inputStream =Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sf =new SqlSessionFactoryBuilder().build(inputStream);
SqlSession ss=sf.openSession();
UserMapper mapper=ss.getMapper(UserMapper.class);
List<User>users=mapper.findAll();
for (User user : users) {
System.out.println(user);
}
ss.close();
}
}
测试结果
Mybatis+Mybatis-plus实现查询User
- 将UserMapper继承BaseMapper,拥有BaseMapper
package cn.itcast.mp.simple.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.itcast.mp.simple.pojo.User;
public interface UserMapper extends BaseMapper<User>{
}
- 使用Mybatis-plus中的MybatisSqlSessionFactoryBuilder构建
package test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
import cn.itcast.mp.simple.mapper.UserMapper;
import cn.itcast.mp.simple.pojo.User;
public class TestMyBatis {
@Test
public void findAll() throws IOException {
InputStream inputStream =Resources.getResourceAsStream("mybatis-config.xml");
// 完成mybatis与Mybatis-plus的整合
SqlSessionFactory sf = new MybatisSqlSessionFactoryBuilder().build(inputStream);
SqlSession ss=sf.openSession();
UserMapper mapper=ss.getMapper(UserMapper.class);
List<User>users=mapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
ss.close();
}
}
执行之后,出现如下错误(提示mp.user不存在)
修改表名
在User对象中添加@TableName,指定数据库表名
package cn.itcast.mp.simple.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
然后再次执行TestMyBatis ,运行结果如下
使用了MybatisSqlSessionFactoryBuilder进行了构建,继承的BaseMapper中的方法就载入到了
SqlSession中,所以就可以直接使用相关的方法;
spring+Mybatis+Mybatis-plus
引入spring框架后,数据源、构建等工作就交给了spring管理
添加maven的jar依赖
<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.0</modelVersion>
<groupId>cn.company</groupId>
<artifactId>mp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<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>
<optional>true</optional>
<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>
<!-- 添加spring的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- 指定Jdk的版本 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
jdbc.properties
数据库连接配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
jdbc.username=root
jdbc.password=root
applicationContext.xml
spring配置文件
<?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">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--定义数据源 -->
<bean class="com.alibaba.druid.pool.DruidDataSource.class" id="dataSource" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="maxActive" value="10"/>
<property name="minIdle" value="5"/>
</bean>
<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
<bean class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--扫描mapper接口,使用的依然是Mybatis原生的扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.itcast.mp.simple.mapper"/>
</bean>
</beans>
编写User对象以及UserMapper接口
package cn.itcast.mp.simple.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
package cn.itcast.mp.simple.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.itcast.mp.simple.pojo.User;
public interface UserMapper extends BaseMapper<User>{
}
测试代码
package test;
import java.util.List;
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.itcast.mp.simple.mapper.UserMapper;
import cn.itcast.mp.simple.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestMyBatisSpring {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
List<User>users=userMapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
SpringBoot + Mybatis + MP
SpringBoot将进一步的简化MP的整合,由于使用SpringBoot需要继承parent,所以需要重新创
建工程
添加maven的jar依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<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>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
添加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
编写application.properties
spring.application.name = mp
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
#mybatis-plus配置控制台打印完整带参数SQL语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
编写User(pojo)
package cn.itcast.mp.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data // 使用lombok注解,开发工具需要安装lombok插件
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
编写mapper
package cn.itcast.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends BaseMapper<User>{
}
编写启动类
package cn.itcast.mp;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("cn.itcast.mp.mapper")//设置mapper接口的扫描包
@SpringBootApplication
public class MpApplication {
public static void main(String[] args) {
SpringApplication.run(MpApplication.class, args);
}
}
测试类
package cn.itcast.mp;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestMybatisSpringBoot {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
List<User>users=userMapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
通用CRUD
通过继承BaseMapper就可以获取各种单表操作
设置ID的生成策略
设置ID的生成为数据库自增长,在实体类字段映射数据库主键的字段上添加@TableId,并设置自增长
package cn.itcast.mp.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(value = "tb_user")
public class User {
@TableId(type = IdType.AUTO) // 数据库自增长
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
测试代码
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user =new User();
user.setEmail("[email protected]");
user.setAge(30);
user.setName("caocao");
user.setUserName("曹操");
user.setPassword("111");
int result =userMapper.insert(user);//返回的result是受影响的行数,并不是自增 后的id
System.out.println("数据库受影响的行数:"+result);
// 获取自增长后的Id
System.out.println("自增长后的Id="+user.getId());
}
}
测试结果
@TableField
在MyBatis-plus中存在以下问题使用@TableField 解决
- 对象中的属性名和字段名不一致
- 对象中的属性字段在表中不存在
对象中的属性和字段名不一致
package cn.itcast.mp.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(value = "tb_user")
public class User {
@TableId(type = IdType.AUTO) // 数据库自增长
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
// private String email;
@TableField(value = "email") // 解决字段名不一致,设置对应数据库中的email列
private String mail;
}
测试代码
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user =new User();
user.setMail("[email protected]");
user.setAge(30);
user.setName("caocao");
user.setUserName("曹操");
user.setPassword("111");
int result =userMapper.insert(user);
System.out.println("数据库受影响的行数:"+result);
// 获取自增长后的Id
System.out.println("自增长后的Id="+user.getId());
}
}
执行结果,控制台输出
数据库中的数据
对象中的属性字段在表中不存在
package cn.itcast.mp.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(value = "tb_user")
public class User {
@TableId(type = IdType.AUTO) // 数据库自增长
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
// private String email;
@TableField(value = "email") // 解决字段名不一致,设置对应数据库中的email列
private String mail;
private String address;
}
测试代码
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user =new User();
user.setMail("[email protected]");
user.setAge(30);
user.setName("caocao");
user.setUserName("曹操");
user.setPassword("111");
user.setAddress("上海");
int result =userMapper.insert(user);
System.out.println("数据库受影响的行数:"+result);
// 获取自增长后的Id
System.out.println("自增长后的Id="+user.getId());
}
}
执行测试代码,junit单元测试不通过
因为在数据库中不存在address列,修改User使其在用户插入数据时不添加address列
package cn.itcast.mp.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(value = "tb_user")
public class User {
@TableId(type = IdType.AUTO) // 数据库自增长
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
// private String email;
@TableField(value = "email") // 解决字段名不一致,设置对应数据库中的email列
private String mail;
@TableField(exist = false) // exist=false表示该字段在数据库中不存在
private String address;
}
重新执行测试代码,控制台输出
查询结果中不显示某个字段
在字段上面添加@TableField(select = false)
package cn.itcast.mp.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(value = "tb_user")
public class User {
@TableId(type = IdType.AUTO) // 数据库自增长
private Long id;
private String userName;
@TableField(select = false) //selecet=false表示在查询时不显示该字段在数据库中的值
private String password;
private String name;
private Integer age;
// private String email;
@TableField(value = "email") // 解决字段名不一致,设置对应数据库中的email列
private String mail;
@TableField(exist = false) // exist=false表示该字段在数据库中不存在
private String address;
}
测试代码
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectByKey() {
User user =userMapper.selectById(7);
System.out.println(user);
}
}
控制台输出password字段值为null
更新
根据id(主键)更新
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testUpdateById() {
User user =userMapper.selectById(7);
user.setAge(35);
int result = userMapper.updateById(user); // result:数据库中发生改变的行数
System.out.println("受影响的行数:"+result);
}
}
测试结果
根据条件更新
通过QueryWrapper条件更新
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testUpdate() {
User user =new User();
// 更新的字段
user.setAge(20);
user.setPassword("8888");
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
queryWrapper.eq("user_name", "zhangsan");//匹配user_name = zhangsan 的用户数据
// 根据条件做更新
int result =userMapper.update(user, queryWrapper);
System.out.println("受影响的行数:"+result);
}
}
测试结果
通过UpdateWrapper进行更新
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testUpdate2() {
UpdateWrapper<User>updateWrapper=new UpdateWrapper<User>();
updateWrapper.set("age",23).set("password","999")//更新的字段
.eq("user_name","zhangsan");//eq:更新的条件
// 根据条件做更新
int result =userMapper.update(null, updateWrapper);
System.out.println("受影响的行数:"+result);
}
}
测试结果
删除
deleteById
根据 ID 删除
测试代码
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MpApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void testDeleteById(){
int result =userMapper.deleteById(7L);
System.out.println("受影响的行:"+result);
}
}
测试结果
数据被删除
deleteByMap
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MpApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void testDeleteByMap(){
Map<String,Object>paramMap=new HashMap<>();
paramMap.put("name","张三");
paramMap.put("age",18);
//将paramMap中的元素设置为删除的条件,多个之间为and关系
int result =userMapper.deleteByMap(paramMap);
System.out.println("受影响的行:"+result);
}
}
测试结果
Delete
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MpApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void testDelete(){
User user=new User();
user.setName("王五");
user.setAge(28);
//将实体对象进行包装,包装为操作条件
QueryWrapper<User>queryWrapper=new QueryWrapper<>(user);
int result=userMapper.delete(queryWrapper);
System.out.println("受影响的行:"+result);
}
}
控制台输出
数据库中的数据
deleteBatchIds
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.*;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MpApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void testDeleteBatchIds(){
//Arrays.asList将数组转换成list集合
int result=userMapper.deleteBatchIds(Arrays.asList(2,5));
System.out.println("受影响的行:"+result);
}
}
测试结果
select
selectById
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MpApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void testSelectById(){
User user =userMapper.selectById(6);
System.out.println(user);
}
}
测试结果
selectBatchIds
package cn.itcast.mp;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.*;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MpApplicationTests {
@Resource
private UserMapper userMapper;
@Test
public void testSelectBatchIds(){
List<User>users=userMapper.selectBatchIds(Arrays.asList(4,6));
for (User user:users) {
System.out.println(user);
}
}
}
selectOne
根据条件查询一条数据,查询结果超过一条会报错
package cn.itcast.mp;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectOne() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
queryWrapper.eq("user_name", "lisi");
//根据条件查询一条数据,结果超过一条会报错
User user=userMapper.selectOne(queryWrapper);
System.out.println(user);
}
}
测试结果
selectCount
查询满足条件的结果的数量
package cn.itcast.mp;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectCount() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
queryWrapper.gt("age",20);// 年龄大于20岁的用户
int count=userMapper.selectCount(queryWrapper);
System.out.println("count="+count);
}
}
测试结果
selectList
package cn.itcast.mp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
queryWrapper.le("age",20);//年龄小于等于20岁的用户
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
selectPage
修改springboot启动类,去除mapper的扫描
package cn.itcast.mp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MpApplication {
public static void main(String[] args) {
SpringApplication.run(MpApplication.class, args);
}
}
添加mybatis-plus配置类
package cn.itcast.mp;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
@MapperScan("cn.itcast.mp.mapper")//设置mapper接口的扫描包
@Configuration
public class MybatisPlusConfig {
@Bean //配置分页插件
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
测试代码
package cn.itcast.mp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectPage() {
//查询第一页,查询4条数据
Page<User>page=new Page<User>(1,4);
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
// 设置查询条件
queryWrapper.like("email", "test");
IPage<User>ipage=userMapper.selectPage(page, queryWrapper);
System.out.println("数据总条数:"+ipage.getTotal());
System.out.println("数据总页数:"+ipage.getPages());
System.out.println("当前页数:"+ipage.getCurrent());
List<User>users=ipage.getRecords();
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
sql注入原理
mybatis-plus在启动后会将BaseMapper中的的方法注册到mappedStatements中
在mybatis-plus中ISqlInjector负责SQL的注入工作,它是一个接口,AbstractSqlInjector是它的实现类
在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的
在实现方法中,methodList.forEach(m->m.inject(builderAssistant,mapperClass,modelClass,tableInfo));是关键,循环遍历方法,进行注入
调用抽象方法injectMappedStatement进行注入
以SelectById为例
生成了SqlSource对象,再将SQL通过addSelectMappedStatement方法添加到mappedStatements中
配置
在mybatis-plus中有一部分是Mybatis原生的配置,另一部分是mybatis-plus的配置
mybatis-plus的配置
基本配置
configLocation
springboot
在application.properties添加如下配置
# 全局的配置文件
mybatis-plus.config-location=classpath:mybatis-config.xml
springmvc的配置文件中添加如下配置
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="configLocation"value="classpath:mybatis-config.xml"/>
</bean>
使用mybatis-config.xml配置分页插件
1、注释掉MybatisPlusConfig中的分页插件
2、在mybatis-config.xml配置分页插件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置插件 -->
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin>
</plugins>
</configuration>
3、测试分页插件
package cn.itcast.mp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserMapper {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectPage() {
//查询第一页,查询4条数据
Page<User>page=new Page<User>(1,1);
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
// 设置查询条件
queryWrapper.like("email", "test");
IPage<User>ipage=userMapper.selectPage(page, queryWrapper);
System.out.println("数据总条数:"+ipage.getTotal());
System.out.println("数据总页数:"+ipage.getPages());
System.out.println("当前页数:"+ipage.getCurrent());
List<User>users=ipage.getRecords();
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
mapperLocations
MyBatis Mapper 所对应的 XML 文件位置,Mapper 中有自定义方法(XML 中有自定义实现),需要进行该配置,告诉 Mapper 所对应的 XML 文件位置
springboot配置文件中的配置
# 扫描classpath下的mybatis文件夹下的所有文件
mybatis-plus.mapper-locations=classpath*:mybatis/*.xml
springmvc中的配置
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
</bean>
添加UserMapper.xml,添加自定义的mapper映射
<?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.itcast.mp.mapper.UserMapper">
<select id="findById" parameterType="java.lang.Long" resultType="cn.itcast.mp.pojo.User">
select * from tb_user where id=#{id}
</select>
</mapper>
package cn.itcast.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends BaseMapper<User>{
User findById(Long id);
}
测试代码
package cn.itcast.mp;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestCase {
@Resource
UserMapper userMapper;
@Test
public void testFindById() {
User user=userMapper.findById(2L);
System.out.println(user);
}
}
测试结果
项目文件结构
typeAliasesPackage
MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名)
在springboot的配置文件application.properties中添加如下配置
# 实体对象扫描的包
mybatis-plus.type-aliases-package=cn.itcast.mp.pojo
在springmvc中的配置如下
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="typeAliasesPackage"
value="cn.itcast.mp.pojo"/>
</bean>
测试代码如下
<?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.itcast.mp.mapper.UserMapper">
<select id="findById" parameterType="java.lang.Long" resultType="User">
select * from tb_user where id=#{id}
</select>
</mapper>
package cn.itcast.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends BaseMapper<User>{
User findById(Long id);
}
package cn.itcast.mp;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestCase {
@Resource
UserMapper userMapper;
@Test
public void testFindById() {
User user=userMapper.findById(2L);
System.out.println(user);
}
}
测试结果
mapUnderscoreToCamelCase
官网介绍
在springboot中的配置
# 禁用自定的驼峰映射,关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
mybatis-plus.configuration.map-underscore-to-camel-case=false
cacheEnabled
官网介绍
在springboot中的配置
# 禁用缓存
mybatis-plus.configuration.cache-enabled=false
DB 策略配置
idType
官网介绍
设置后,可省略实体对象中的@TableId(type = IdType.AUTO)配置。(数据库自增长的方式)
SpringBoot中的配置
# 全局的id生成策略
mybatis-plus.global-config.db-config.id-type=auto
SpringMVC中的配置
<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="globalConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean
class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<property name="idType" value="AUTO"/>
</bean>
</property>
</bean>
</property>
</bean>
tablePrefix
官网介绍
表名前缀,全局配置后可省略@TableName()配置。
SpringBoot
# 全局的表名的前缀
mybatis-plus.global-config.db-config.table-prefix=tb_
SpringMVC中的配置
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="globalConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<property name="idType" value="AUTO"/>
<property name="tablePrefix" value="tb_"/>
</bean>
</property>
</bean>
</property>
</bean>
配置之后,测试查询(数据库中表名为tb_user)
条件构造器
在mybatis-plus中,Wrapper接口的实现类关系如下
AbstractWrapper和AbstractChainWrapper是重点实现
官网介绍
allEq
package cn.itcast.mp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestCase {
@Resource
UserMapper userMapper;
@Test
public void testAllEq() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
Map<String,Object>params=new HashMap<String,Object>();
params.put("name","李四");
params.put("age",20);
params.put("password",null);
queryWrapper.allEq(params);
/*
* 查询的测试语句
* SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE password IS NULL AND name = ? AND age = ?
*/
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果:没有符合条件的数据
个别参数说明(isNull)
测试代码
package cn.itcast.mp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestCase {
@Resource
UserMapper userMapper;
@Test
public void testAllEq2() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
Map<String,Object>params=new HashMap<String,Object>();
params.put("name","李四");
params.put("age",20);
params.put("password",null);
queryWrapper.allEq(params, false);
/*
* 查询的测试语句
* SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE name = ? AND age = ?
*/
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
个别参数:filter
filter : 过滤函数,是否允许字段传入比对条件中(对传入的params进行过滤,符合过滤条件才作为参数)
params 与 null2IsNull : 同上
package cn.itcast.mp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestCase {
@Resource
UserMapper userMapper;
@Test
public void testAllEq3() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
Map<String,Object>params=new HashMap<String,Object>();
params.put("name","李四");
params.put("age",20);
params.put("password",null);
//(k,v)->(k.equals("age")传入的参数的名等于age才作为查询参数
queryWrapper.allEq((k,v)->(k.equals("age")),params, false);
/*
* 查询的测试语句
* SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE age = ?
*/
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
查询结果
基本操作
- eq 等于= 官网介绍
- ne 不等于<> 官网介绍
- gt 大于> 官网介绍
- ge 大于等于>= 官网介绍
- lt 小于< 官网介绍
- le 小于等于<= 官网介绍
- between between 值1 and 值2 官网介绍
- notBetween notBetween 值1 and 值2 官网介绍
- in 字段in(value.get(0),value.get(1)) 官网介绍
模糊查询
package cn.itcast.mp;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Resource
UserMapper userMapper;
@Test
public void testLike() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
/**
* 查询语句
* SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE name LIKE ?
* 参数为 %五
*/
queryWrapper.likeLeft("name","五");
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
排序
package cn.itcast.mp;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Resource
UserMapper userMapper;
@Test
public void test() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
/**
* 按照年龄倒序排序
* 查询语句
* SELECT id,user_name,password,name,age,email AS mail FROM tb_user ORDER BY age DESC
* 参数为 %五
*/
queryWrapper.orderByDesc("age");
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
逻辑查询
package cn.itcast.mp;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Resource
UserMapper userMapper;
@Test
public void test() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
/**
* 查询语句:SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE name = ? OR age = ?
* 参数:王五,21
*/
queryWrapper.eq("name", "王五").or().eq("age", 21);
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
select
官网介绍
默认查询所有的字段,如果有需要也可以通过select方法进行指定字段
package cn.itcast.mp;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Resource
UserMapper userMapper;
@Test
public void test() {
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
/**
* 查询语句: SELECT id,name,age FROM tb_user WHERE name = ? OR age = ?
* 参数:王五,21
*/
queryWrapper.eq("name", "王五").or().eq("age", 21).select("id","name","age");//指定查询的字段
List<User>users=userMapper.selectList(queryWrapper);
for (User user : users) {
System.out.println(user);
}
}
}
测试结果
ActiveRecord
简称AR
ActiveRecord也属于ORM(对象关系映射)层,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂
- Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录
- 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field
- ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD
根据主键查询
开启ActiveRecord,只需要将实体对象继承Model即可
开启ActiveRecord模式,需要有对应的mapper并继承baseMapper,才能使用ActiveRecord模式
如User对应的mapper(UserMapper继承BaseMapper
代码如下
package cn.itcast.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends BaseMapper<User>{
}
根据主键查询
package cn.itcast.mp.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 com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends Model<User>{
private Long id;
private String userName;
@TableField(select = true) //selecet=false表示在查询时不显示该字段在数据库中的值
private String password;
private String name;
private Integer age;
@TableField(value = "email") // 解决字段名不一致,设置对应数据库中的email列
private String mail;
@TableField(exist = false) // exist=false表示该字段在数据库中不存在
private String address;
}
package cn.itcast.mp;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Test
public void test() {
/**
* 查询语句: SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE id=?
* 参数:2
* 查询结果
* User(id=2, userName=lisi, password=123456, name=李四, age=20, [email protected], address=null)
*/
User user =new User();
user.setId(2L);
User user2=user.selectById();
System.out.println(user2);
}
}
新增数据
package cn.itcast.mp;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Test
public void test() {
/**
* sql语句:INSERT INTO tb_user ( user_name, password, name, age ) VALUES ( ?, ?, ?, ? )
* 参数:liubei(String), 123(String), 刘备(String), 20(Integer)
* 返回true
*/
User user =new User();
user.setName("刘备");
user.setUserName("liubei");
user.setPassword("123");
user.setAge(20);
boolean result=user.insert();
System.out.println("数据新增成功:"+result);
}
}
测试结果
根据主键更新数据
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Test
public void test() {
/**
*sql语句:
*UPDATE tb_user SET age=? WHERE id=?
*参数:
*30,10
*返回结果为true
*/
User user =new User();
user.setId(10L);// 设置查询条件
user.setAge(30);// 更新的数据
boolean result=user.updateById();
System.out.println("更新数据是否成功:"+result);
}
}
根据主键删除数据
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Test
public void test() {
/**
*sql语句:DELETE FROM tb_user WHERE id=?
*参数:10
*返回结果为true
*/
User user =new User();
user.setId(10L);// 设置查询条件
boolean result=user.deleteById();
System.out.println(result);
}
}
根据条件查询
package cn.itcast.mp;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestQueryDemo {
@Test
public void test() {
/**
* sql语句:SELECT id,user_name,password,name,age,email AS mail FROM tb_user WHERE age >= ?
* 查询参数:30
* 查询结果:
* User(id=6, userName=曹操, password=111, name=caocao, age=30, [email protected], address=null)
* User(id=8, userName=曹操, password=111, name=caocao, age=30, [email protected], address=null)
*/
QueryWrapper<User>queryWrapper=new QueryWrapper<User>();
queryWrapper.ge("age",30);//大于等于30岁的用户
User user=new User();
List<User>users=user.selectList(queryWrapper);
for (User user2 : users) {
System.out.println(user2);
}
}
}
插件
mybatis插件机制
- MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。
- 默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
-
- 拦截执行器的方法:Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
-
- 拦截参数的处理 :ParameterHandler (getParameterObject, setParameters)
-
- 拦截结果集的处理:ResultSetHandler (handleResultSets, handleOutputParameters)
-
- 拦截Sql语法构建的处理:StatementHandler (prepare, parameterize, batch, update, query)
- 可以拦截Executor接口的部分方法,update,query,commit,rollback等方法,还有其他接口的一些方法等。
- 总体概括为:
1. 拦截执行器的方法
2. 拦截参数的处理
3. 拦截结果集的处理
4. 拦截Sql语法构建的处理
实例代码
package cn.itcast.mp.plugins;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
/**
* type:拦截的类型,Executors
* method:拦截的是执行器中的update方法
* @author 86182
*
*/
@Intercepts({
@Signature(type=Executor.class,method = "update",
args= {
MappedStatement.class,Object.class})})
public class MyInterceptor implements Interceptor{
@Override
public Object intercept(Invocation invocation) throws Throwable {
//拦截方法,具体业务逻辑编写的位置
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
//创建target对象的代理对象,目的是将当前拦截器加入到该对象中
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
//属性设置
}
}
在springboot的mybatis的配置类中配置自定义的拦截器
package cn.itcast.mp;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser;
import com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor;
import cn.itcast.mp.plugins.MyInterceptor;
@MapperScan("cn.itcast.mp.mapper") // 设置mapper接口的扫描包
@Configuration
public class MybatisPlusConfig {
// 注入自定义的拦截器(插件)
@Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
}
执行分析插件
mybatis-plus提供了对SQL执行的分析的插件,可作用于阻断全表更新、删除的操作
该插件仅适用于开发环境,不适用于生产环境(影响性能)
SpringBoot配置:
在springboot中mybatis的配置类中添加分析插件
package cn.itcast.mp;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser;
import com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor;
@MapperScan("cn.itcast.mp.mapper") // 设置mapper接口的扫描包
@Configuration
public class MybatisPlusConfig {
@Bean // SQL分析插件
public SqlExplainInterceptor sqlExplainInterceptor() {
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List<ISqlParser> list = new ArrayList<>();
//攻击SQL阻断解析器、加如解析链
list.add(new BlockAttackSqlParser()); // 全表更新、删除的阻断器
sqlExplainInterceptor.setSqlParserList(list);
return sqlExplainInterceptor;
}
}
测试类
package cn.itcast.mp;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cn.itcast.mp.mapper.UserMapper;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestDemo {
@Resource
UserMapper userMapper;
/**
* 测试全表更新,SQL分析器阻断效果
*/
@Test
public void test() {
User user=new User();
user.setAge(20);
int count=userMapper.update(user, null);
System.out.println("count="+count);
}
/**
* 表格单个更新可以执行,执行的sql如下:
* UPDATE tb_user SET age=? WHERE id=?
* 参数:20,2
* 结果为count=1
*/
@Test
public void testUpdateOne() {
User user=new User();
user.setId(2L);
user.setAge(20);
int count=userMapper.updateById(user);
System.out.println("count="+count);
}
}
执行test方法,测试结果如下,提示禁止表更新操作
性能分析插件
性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常
此插件只适用于开发环境,不建议生产环境使用
在springboot配置文件application.properties中添加Mybatis-plus的配置文件的路径
# 全局的配置文件
mybatis-plus.config-location=classpath:mybatis-config.xml
在Mybatis-plus的配置文件中配置性能分析插件
<?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>
<!-- 配置插件 -->
<plugins>
<!--性能分析插件 -->
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
<!--最大的执行时间,单位为毫秒-->
<property name="maxTime" value="10"/>
<!--对输出的SQL做格式化,默认为false-->
<property name="format" value="true"/>
</plugin>
</plugins>
</configuration>
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestDemo {
@Test
public void testSelectById() {
User user=new User();
user.setId(11L);
User user1=user.selectById();
System.out.println(user1);
}
}
测试结果
控制台打印sql和执行时间
单元测试提示测试时间过长,需要优化
乐观锁插件
乐观锁官网介绍
目的:当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
在Mybatis-plus的配置文件中配置乐观锁插件
<?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>
<!-- 配置插件 -->
<plugins>
<!-- 乐观锁插件,完成每次版本字段的自动增加 -->
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor">
</plugin>
</plugins>
</configuration>
为表添加version字段,并且设置初始值为1
ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`;
UPDATE`tb_user`SET`version`='1';
为User实体对象添加version字段,并且添加@Version注解:
@Version //乐观锁的版本字段
private Integer version;
测试代码
package cn.itcast.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.mp.pojo.User;
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestDemo {
/**
* 测试乐观锁
*/
@Test
public void testUpdateVersion() {
User user = new User();
user.setId(2L);// 查询条件
User userVersion = user.selectById();
user.setAge(25);// 更新的数据
user.setVersion(userVersion.getVersion());// 当前的版本信息
boolean result=user.updateById();
System.out.println("result=>"+result);
}
}
测试结果
可以看到,更新的条件中有version条件,并且更新的version为2
Sql 注入器
在Mybatis-pllus中,通过AbstractSqlInjector将BaseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行
如果需要扩充BaseMapper中的方法,实现方法如下
编写MyBaseMapper
package cn.itcast.mp.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface MyBaseMapper <T> extends BaseMapper<T>{
List<T>findAll();
}
其他的Mapper都可以继承该Mapper,这样实现了统一的扩展
如UserMapper
package cn.itcast.mp.mapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends MyBaseMapper<User>{
User findById(Long id);
}
https://www.bilibili.com/video/BV1oD4y1m74N?p=58