1. 简介 MyBatis 是⼀款优秀的基于 ORM 的半⾃动轻量级持久层框架,它⽀持定制化 SQL、存储过程以及⾼级映 射。MyBatis 避免了⼏乎所有的JDBC代码和⼿动设置参数以及获取结果集。MyBatis 可以使⽤简单的 XML或注解来配置和映射原⽣类型、接⼝和 Java 的 POJO (Plain Old Java Objects,普通⽼式 Java 对象) 为数据库中的记录。
Tips: 官网地址
2. 快速使用
使用步骤:① 添加依赖 - ② 创建表 - ③ 创建实体 - ④ 创建 mapper 文件 - ⑤ 创建核心配置文件 sqlMapConfig.xml - ⑥ 编写测试类
2.1 引入依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <?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" > <modelVersion > 4.0.0</modelVersion > <groupId > tech.fengjian</groupId > <artifactId > mybatis-quickstart</artifactId > <version > 1.0-SNAPSHOT</version > <dependencies > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.28</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.9</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <version > 3.1</version > <configuration > <source > 1.8</source > <target > 1.8</target > <encoding > utf-8</encoding > </configuration > </plugin > </plugins > </build > </project >
2.2 定义实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class User { private Integer id; private String username; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } }
2.3 新建实体类对应的表 1 2 3 4 5 CREATE TABLE `user ` ( `id` int (11 ) NOT NULL AUTO_INCREMENT, `username` varchar (255 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE= InnoDB AUTO_INCREMENT= 8 DEFAULT CHARSET= utf8mb4;
2.4 核心配置文件 2.4.1 SqlConfig.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?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.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="UserMapper.xml" /> </mappers> </configuration>
2.4.2 mapper.xml 1 2 3 4 5 6 7 8 9 10 <?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 ="UserMapper" > <select id ="findAll" resultType ="tech.fengjian.pojo.User" > select * from User </select > </mapper >
2.5 编写dao 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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 java.io.IOException;import java.io.InputStream;import java.util.List;public class UserDao { List<User> findAll () throws IOException { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> userList = sqlSession.selectList("UserMapper.findAll" ); sqlSession.close(); return userList; } }
Tips: UserDao 的方式有一个冗余的部分UserMapper.findAll,每增加一个方法,都需要指定 Mapper 和 方法;mybatis利用代理模式做了优化,约定如下:
1)编写接口,接口全路径即 namespace 2)接口方法即 sql 的 id 3)接口方法返回值即 sql 的 resultType 4)接口方法的参数即 sql 的 parameterType
所以我们可以修改 UserDao 代码为 UserMapper:
1 2 3 4 5 6 7 import java.util.List;public interface UserMapper { List<User> findAll () ; }
2.6 测试 2.6.1 UserDao 方式(传统写法) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.io.IOException;import java.util.List;public class Test { public static void main (String[] args) throws IOException { UserDao userDao = new UserDao(); List<User> userList = userDao.findAll(); for (User user : userList) { System.out.println(user); } } }
2.6.2 UserMapper 接口方式(推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 java.io.IOException;import java.io.InputStream;import java.util.List;public class Test { public static void main (String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.findAll(); for (User user : userList) { System.out.println(user); } } }
2.7 mybatis 核心配置文件详解
mybatis 核心配置文件中的标签是有顺序的!!!
2.7.1 properties 标签 习惯将数据源单独抽出到一个配置文件,使用properties标签就可以加载额外的 properties 文件
jdbc.properties:
1 2 3 4 jdbc.mysql.driver = com.mysql.cj.jdbc.Driver jdbc.mysql.url = jdbc:mysql://localhost:3306/mybatis jdbc.mysql.user = root jdbc.mysql.password = 123456
那么相应的 SqlMapConfig.xml 修改后如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <properties resource ="jdbc.properties" /> <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${jdbc.mysql.driver}" /> <property name ="url" value ="${jdbc.mysql.url}" /> <property name ="username" value ="${jdbc.mysql.user}" /> <property name ="password" value ="${jdbc.mysql.password}" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="UserMapper.xml" /> </mappers > </configuration >
2.7.2 typeAlias 标签 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
1 2 3 <typeAliases > <typeAlias alias ="User" type ="tech.fengjian.pojo.User" /> </typeAliases >
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
1 2 3 <typeAliases > <package name ="tech.fengjian.pojo" /> </typeAliases >
配置后,mapper.xml 中的类型则可以简写:
1 2 3 4 <select id ="findAll" resultType ="User" > select * from User </select >
Tips: 别名的使用不区分大小写!
1 2 3 4 <select id ="findAll" resultType ="User" > select * from User </select >
跟
1 2 3 4 <select id ="findAll" resultType ="uSEr" > select * from User </select >
是一样的!
2.7.3 environments 标签 MyBatis 可以配置成适应多种环境,例如,开发、测试和生产环境需要有不同的配置
1 2 3 4 5 6 7 8 9 10 11 12 <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${jdbc.mysql.driver}" /> <property name ="url" value ="${jdbc.mysql.url}" /> <property name ="username" value ="${jdbc.mysql.user}" /> <property name ="password" value ="${jdbc.mysql.password}" /> </dataSource > </environment > </environments >
注意一些关键点:
默认使用的环境 ID(比如:default=”development”)。
每个 environment 元素定义的环境 ID(比如:id=”development”)。
事务管理器的配置(比如:type=”JDBC”)。
数据源的配置(比如:type=”POOLED”)。
事务管理器(transactionManager)
有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):
UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。
JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。
2.7.4 mappers 标签 SQL 映射器:告诉 MyBatis 到哪里去找到 sql 语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件
使用相对于类路径(classpath)的资源引用
1 2 3 4 5 <mappers > <mapper resource ="org/mybatis/builder/AuthorMapper.xml" /> <mapper resource ="org/mybatis/builder/BlogMapper.xml" /> <mapper resource ="org/mybatis/builder/PostMapper.xml" /> </mappers >
使用完全限定资源定位符(URL)
1 2 3 4 5 <mappers > <mapper url ="file:///var/mappers/AuthorMapper.xml" /> <mapper url ="file:///var/mappers/BlogMapper.xml" /> <mapper url ="file:///var/mappers/PostMapper.xml" /> </mappers >
使用映射器接口实现类的完全限定类名
1 2 3 4 5 <mappers > <mapper class ="org.mybatis.builder.AuthorMapper" /> <mapper class ="org.mybatis.builder.BlogMapper" /> <mapper class ="org.mybatis.builder.PostMapper" /> </mappers >
将包内的映射器接口全部注册为映射器
1 2 3 <mappers > <package name ="org.mybatis.builder" /> </mappers >
Tips: 方式 3 和方式 4 要求 mapper.xml 文件目录同 mapper 接口包路径一致,编译后都在同一个 calsses 路径下
3. 复杂映射查询 3.1 一对一 需求: 查询订单及订单所属用户信息(一个订单只能属于一个用户)
订单表:
1 2 3 4 5 6 create table orders( id int (11 ) primary key auto_increment not null comment '主键ID' , ordertime varchar (32 ) not null comment '下单时间' , total double (10 ,2 ) not null comment '订单金额' , uid int (11 ) not null comment '用户ID' );
用户表:
3.1.1 实体类
User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package tech.fengjian;public class User { private Integer id; private String username; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } }
Order
OrderMapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?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 ="tech.fengjian.OrderMapper" > <resultMap id ="orderMap" type ="tech.fengjian.Order" > <result column ="id" property ="id" /> <result column ="order_time" property ="order_time" /> <result column ="total" property ="total" /> <association property ="user" javaType ="tech.fengjian.User" > <result column ="uid" property ="id" /> <result column ="username" property ="username" /> </association > </resultMap > <select id ="findAll" resultMap ="orderMap" > select * from `order` o,user u where o.uid=u.id; </select > </mapper >
3.1.2 Mapper 接口 1 2 3 4 5 6 7 8 9 10 package tech.fengjian;import java.util.List;public interface OrderMapper { List<Order> findAll () ; }
3.2 一对多 查询用户及用户的订单:
3.2.1 实体类
User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package tech.fengjian;import java.util.List;public class User { private Integer id; private String username; private List<Order> order_list; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + '}' ; } }
Order
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package tech.fengjian;import java.util.Date;public class Order { private Integer id; private Date order_time; private double total; private User user; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public Date getOrder_time () { return order_time; } public void setOrder_time (Date order_time) { this .order_time = order_time; } public double getTotal () { return total; } public void setTotal (double total) { this .total = total; } public User getUser () { return user; } public void setUser (User user) { this .user = user; } @Override public String toString () { return "Order{" + "id=" + id + ", order_time=" + order_time + ", total=" + total + ", user=" + user + '}' ; } }
UserMapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?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 ="tech.fengjian.UserMapper" > <resultMap id ="userMap" type ="tech.fengjian.User" > <result property ="id" column ="id" /> <result property ="username" column ="username" /> <collection property ="order_list" ofType ="tech.fengjian.Order" > <result property ="id" column ="oid" /> <result property ="order_time" column ="order_time" /> <result property ="total" column ="total" /> </collection > </resultMap > <select id ="findAll" resultMap ="userMap" > select *,o.id oid from user u left join `order` o on u.id=o.uid </select > </mapper >
3.3 多对多 查询用户及拥有的角色:
涉及的表 user role user_role(中间表)
UserMapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 <resultMap id ="userRoleMap" type ="tech.fengjian.User" > <result property ="id" column ="id" /> <result property ="username" column ="username" /> <collection property ="role_list" ofType ="tech.fengjian.Role" > <result property ="id" column ="rid" /> <result property ="name" column ="name" /> </collection > </resultMap > <select id ="findAllUserWithRole" resultMap ="userRoleMap" > select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.userid inner join role r on ur.roleid=r.id;</select >
4. 缓存 一级缓存:基于 sqlSession
同一个 sqlSession 两次查询,mybatis 会直接从缓存中获取
若两次查询中间涉及增、删、改,则缓存失效(sqlSession 执行了 commit 操作)
二级缓存:基于 Mapper 文件的 namespace
二级缓存需要手动开启
若两次查询中间涉及增、删、改,则缓存失效(sqlSession 执行了 commit 操作)
5. 插件 mybatis 插件 涉及四大组件:Executor、StatementHandler、ParameterHandler、ResultSetHandler
5.1 自定义插件 5.1.1 定义插件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package tech.fengjian;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.util.Properties;@Intercepts({ @Signature( type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} ) }) public class MyPlugin implements Interceptor { public Object intercept (Invocation invocation) throws Throwable { System.out.println("对query方法进行增强" ); return invocation.proceed(); } public Object plugin (Object target) { System.out.println("增强的目标对象:" +target); return Plugin.wrap(target,this ); } public void setProperties (Properties properties) { System.out.println("初始化属性:" +properties); } }
5.1.2 注册插件 1 2 3 4 5 6 7 <plugins > <plugin interceptor ="tech.fengjian.MyPlugin" > <property name ="key1" value ="value1" /> <property name ="key2" value ="value2" /> </plugin > </plugins >
5.2 通用 mapper
提供一些通用的 sql 以便快速开发
5.2.1 引入依赖
5.2.2 注册插件 1 2 3 4 <plugin interceptor ="tk.mybatis.mapper.mapperhelper.MapperInterceptor" > <property name ="mappers" value ="tk.mybatis.mapper.common.Mapper" /> </plugin >
5.2.3 插件使用
实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package tech.fengjian;import javax.persistence.Transient;import java.util.List;public class User { private Integer id; private String username; @Transient private List<Order> order_list; @Transient private List<Role> role_list; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public List<Order> getOrder_list () { return order_list; } public void setOrder_list (List<Order> order_list) { this .order_list = order_list; } public List<Role> getRole_list () { return role_list; } public void setRole_list (List<Role> role_list) { this .role_list = role_list; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", order_list=" + order_list + ", role_list=" + role_list + '}' ; } }
提示:
不需要查询的字段使用 @Transient 注解标记
Mapper 接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package tech.fengjian;import tk.mybatis.mapper.common.Mapper;public interface UserMapper extends Mapper <User > { }
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 tech.fengjian.User;import tech.fengjian.UserMapper;import java.io.IOException;import java.io.InputStream;import java.util.List;public class Test { public static void main (String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setId(1 ); List<User> userList = mapper.select(user); System.out.println(userList); } }
5.3 分页插件 5.3.1 引入依赖 1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 3.7.5</version > </dependency > <dependency > <groupId > com.github.jsqlparser</groupId > <artifactId > jsqlparser</artifactId > <version > 0.9.1</version > </dependency >
5.3.2 注册插件
分页插件应先于通用 mapper 插件注册,注意注册顺序
1 2 3 <plugin interceptor ="com.github.pagehelper.PageHelper" > <property name ="dialect" value ="mysql" /> </plugin >
5.3.2 测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import com.github.pagehelper.PageHelper;import com.github.pagehelper.PageInfo;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 tech.fengjian.User;import tech.fengjian.UserMapper;import java.io.IOException;import java.io.InputStream;import java.util.List;public class Test { public static void main (String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); PageHelper.startPage(1 ,10 ); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> orderList = mapper.findAll(); PageInfo<User> userPageInfo = new PageInfo<User>(orderList); System.out.println(userPageInfo.getTotal()); } }
6. mybatis-plus 的使用
MyBatis-Plus(简称 MP)是⼀个 MyBatis 的增强⼯具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提⾼效率⽽⽣
提示: 引入 mybatis-plus 后不要再次引入 mybatis 及 mybatis-spring 依赖,以免版本问题导致异常问题
6.1 急速入门( SpringBoot项目 ) 6.1.1 引入依赖 1 2 3 4 5 <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.1.1</version > </dependency >
6.1.2 编写实体类 1 2 3 4 5 6 7 8 9 @Data @NoArgsConstructor @AllArgsConstructor public class User { private Integer id; private String username; }
6.1.3 编写 mapper 1 2 3 public interface UserMapper extends BaseMapper <User > { }
6.1.4 扫描 mapper 1 2 3 4 5 6 7 8 9 @MapperScan("tech.fengjian.springbootmybatisplus.mapper") @SpringBootApplication public class SpringbootMybatisPlusApplication { public static void main (String[] args) { SpringApplication.run(SpringbootMybatisPlusApplication.class, args); } }
6.1.5 测试 1 2 3 4 5 6 7 8 9 10 11 12 13 @SpringBootTest class SpringbootMybatisPlusApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads () { List<User> userList = userMapper.selectList(null ); System.out.println(userList); } }
6.2 常用的一些注解释义 @TableName("tb_user"): 若数据库表名与实体类名称不一致,可以手动指定表名
@TableId(type = IdType.AUTO): 主键 id 生成策略
AUTO (自增)
NONE (未设置)
INPUT (用户输入)
ID_WORKER (全局唯一)
UUID (全局唯一)
ID_WORKER_STR (全局唯一)
@TableField:
对象中的属性名和字段名不⼀致的问题(⾮驼峰)
对象中的属性字段在表中不存在的问题
字段不加⼊查询字段
1 2 3 4 5 6 7 8 9 10 11 12 13 @Data @NoArgsConstructor @AllArgsConstructor public class User { @TableField(select = false) private Integer id; @TableField(value = "username") private String name; @TableField(exist = false) private String email; }
6.3 基本配置 基础配置
configLocation 指定配置文件位置
1 mybatis-plus.config-location = classpath:mybatis-config.xml
mapperLocations 指定 mapper 文件位置
1 mybatis-plus.mapper-locations = classpath*:mybatis/*.xml
进阶配置
mapUnderscoreToCamelCase: 自动转驼峰,默认 true
1 2 mybatis-plus.configuration.map-underscore-to-camel-case =false
cacheEnabled: 开启缓存,默认 true
1 mybatis-plus.configuration.cache-enabled =false
DB 配置
idType: 全局默认主键类型,不用每个实体类配置了
1 mybatis-plus.global-config.db-config.id-type =auto
tablePrefix:全局表前缀
1 mybatis-plus.global-config.db-config.table-prefix =tb_
6.4 QueryWrapper 条件构造器 6.4.1 基本比较 allEq:
方法重载:
1 2 3 allEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
参数说明: params : key 数据库字段,value 查询的值 null2IsNull: 是否将 params 中的 null 值转为 sql 中的 is null,false 表示忽略 condition: true 则进行条件构造,false 不进行
1 2 3 4 allEq(BiPredicate<R, V> filter, Map<R, V> params) allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
参数说明: filter: 对 params 进行过滤
eq: =
ne: <>
gt: >
ge: >=
lt: <
le: <=
between: between 值 1 and 值 2
notBetween: not between 值 1 and 值 2
in: 字段 in (值1,值2,…)
notin: 字段 not in (值1,值2,…)
提示:
LambdaQueryWrapper 支持链式调用!!!
6.4.2 模糊查询 like: like(‘name’,’jack’) -> name like ‘%jack%’notlike: notlike(‘name’,’jack’) -> name not like ‘%jack%’likeleft: likeleft(‘name’,’jack’) -> name like ‘%jack’likeright: likeright(‘name’,’jack’) -> name like ‘jack%’
6.4.2 排序 orderBy: orderBy(true, true, “id”, “name”) —> order by id ASC,name ASCorderByDesc: orderByAsc(“id”, “name”) —> order by id ASC,name ASCorderByAsc: orderByDesc(“id”, “name”) —> order by id DESC,name DESC
6.4.3 or and 多条件默认 and 连接,使用 or() 则使用 or 拼接sql
6.4.4 select 指定查询字段 select(‘name’,’age’) 指定查询的字段,默认是全字段
6.5 常用插件 6.5.1 插件注册
方式一:注入到 Spring 容器
1 2 3 4 @Bean public MyInterceptor myInterceptor () { return new MyInterceptor(); }
方式二:mybatis 核心配置文件中注册
1 2 3 4 5 6 7 8 9 <?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.lagou.mp.plugins.MyInterceptor" > </plugin > </plugins > </configuration >
6.5.2 执行分析插件
开发环境使用
1 2 3 4 5 6 7 8 9 10 @Bean public SqlExplainInterceptor sqlExplainInterceptor () { SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor(); List<ISqlParser> sqlParserList = new ArrayList<>(); sqlParserList.add(new BlockAttackSqlParser()); sqlExplainInterceptor.setSqlParserList(sqlParserList); return sqlExplainInterceptor; }
当执⾏全表更新时,会抛出异常,这样有效防⽌了⼀些误操作.
6.5.3 性能分析插件
开发环境使用
1 2 3 4 5 6 7 8 @Bean public PerformanceInterceptor performanceInterceptor () { PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor(); performanceInterceptor.setFormat(true ); performanceInterceptor.setMaxTime(1 ); return performanceInterceptor; }
6.5.4 乐观锁插件
取出记录时,获取当前version
更新时,带上这个version
执⾏更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
1 2 3 4 5 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor () { return new OptimisticLockerInterceptor(); }
数据表增加 version 字段
1 2 3 ALTER TABLE `user `ADD COLUMN `version` int (10 ) NULL AFTER `email`; UPDATE `user ` SET `version`= '1' ;
实体类增加 @Version 注解
1 2 @Version private Integer version;
6.5 Sql 注入器,扩充 BaseMapper
BaseMapper 提供的默认方法不够用了,自己搞
原理:mybatis-plus 利用 AbstractSqlInjector 将 BaseMapper 中方法注入到了 mybatis 中
6.5.1 MyBaseMapper 1 2 3 4 public interface MyBaseMapper <T > extends BaseMapper <T > { List<T> findAll () ; }
6.5.2 MySqlInjector 1 2 3 4 5 6 7 8 9 public class MysqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList () { List<AbstractMethod> methodList = super .getMethodList(); methodList.add(new FindAll()); return methodList; } }
6.5.3 FindAll 1 2 3 4 5 6 7 8 9 10 11 public class FindAll extends AbstractMethod { @Override public MappedStatement injectMappedStatement (Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sqlMethod = "findAll" ; String sql = "select * from " + tableInfo.getTableName(); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this .addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo); } }
6.5.4 添加到 Spring 容器 1 2 3 4 5 6 7 8 @Configuration public class InjectorConfiguration { @Bean public MysqlInjector mysqlInjector () { return new MysqlInjector(); } }
提示:
如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的⽅法将失效,所以我们选择继承 DefaultSqlInjector进⾏扩展.
6.6 逻辑删除
修改表结构,添加 deleted 字段
1 2 3 ALTER TABLE `user `ADD COLUMN `deleted` int (1 ) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER `version`;
实体类添加 @TableLogic 注解
1 2 @TableLogic private Integer deleted;
新增配置,指定逻辑删除字段的值
1 2 3 4 mybatis-plus.global-config.db-config.logic-delete-value =1 mybatis-plus.global-config.db-config.logic-not-delete-value =0
6.7 基于 mapper 接口的 idea 插件 mybatisx 实现:
1)java 与 XML 代码互跳 2)自动生成 statement
完