一、mybatis-plus概念
官方文档:https://baomidou.com/guide/
mybatis使用方式是直接在xml中通过SQL语句操作数据库,包括简单的CRUD操作都必须
要写SQL语句,而mybatis-plus在Mybatis基础上扩展了许多功能,对CRUD的封装、代码
生成器等,很好的提高基于MyBatis 的项目开发效率。
二、mybatis-plus的安装配置
Spring Boot中快速使用
1,引入pom.xml依赖
1 <!-- mybatis-plus-->
2 <dependency>
3 <groupId>com.baomidou</groupId>
4 <artifactId>mybatis-plus-boot-starter</artifactId>
5 <version>3.0.3</version>
6 </dependency>
2,配置application-test.yml
1 mybatis-plus:
2 configuration:
3 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
4 mapper-locations: classpath:mapping/*Mapping.xml #配置自定义sql时Mapping.xml扫描的路径
5 type-aliases-package: com.example.demo.*.entity #配置三扫码的实体类路径
6 global-config:
7 db-config:
8 logic-delete-value: 1 # 逻辑已删除值(默认为 1)
9 logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
10 id-type: none
3,Application 配置 MapperScan 注解
1 @MapperScan("com.example.demo.*.mapper")
2 @SpringBootApplication
3 public class DemoApplication {
4 public static void main(String[] args) {
5 SpringApplication.run(DemoApplication.class, args);
6 }
7 }三、mybatis-plus的代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成
Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升
了开发效率。
1,引入pom.xml依赖
1 <!-- mp自动代码生成-->
2 <dependency>
3 <groupId>com.baomidou</groupId>
4 <artifactId>mybatis-plus-generator</artifactId>
5 <version>3.0.3</version>
6 </dependency>
7 <!-- velocity 模板引擎, 默认 -->
8 <dependency>
9 <groupId>org.apache.velocity</groupId>
10 <artifactId>velocity-engine-core</artifactId>
11 <version>2.0</version>
12 </dependency>
13
14 <!-- freemarker 模板引擎 -->
15 <dependency>
16 <groupId>org.freemarker</groupId>
17 <artifactId>freemarker</artifactId>
18 <version>2.3.23</version>
19 </dependency>
20
21 <!-- beetl 模板引擎 -->
22 <dependency>
23 <groupId>com.ibeetl</groupId>
24 <artifactId>beetl</artifactId>
25 <version>2.2.5</version>
26 </dependency>
2,引入代码生成器模板类 MysqlGenerator.java
3,配置数据源地址、生成路径和表名及其他自定义属性3.1:配置生成路径
1 //当前路径
2 String projectPath = System.getProperty("user.dir");
3 //输出路径
4 gc.setOutputDir(projectPath + "/src/main/java");
3.2: 数据源配置
1 // 数据源配置
2 DataSourceConfig dsc = new DataSourceConfig();
3 dsc.setUrl("jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&useUnicode=true&useJ
4 // dsc.setSchemaName("public");
5 dsc.setDriverName("com.mysql.cj.jdbc.Driver");
6 dsc.setUsername("root");
7 dsc.setPassword("123456");
8 dsc.setDbType(DbType.MYSQL); //指定数据库的类型
9 mpg.setDataSource(dsc);
3.3:包配置
1 // 包配置
2 PackageConfig pc = new PackageConfig();
3 pc.setParent("com.example.demo.test"); //自定义包的路径
4 //pc.setModuleName("module"); //模块名称 设置后,会生成com.cxyxs.test.module,里面存放之前设
5 pc.setEntity("entity");
6 pc.setMapper("mapper");
7 pc.setService("service");
8 pc.setController("controller");
9 mpg.setPackageInfo(pc);
3.4:设置要生成的表
1 // 策略配置
2 StrategyConfig strategy = new StrategyConfig();
3 strategy.setInclude("t_test"); //设置映射的表名,可以设置多个表4:运行main方法生成代码文件
四、mybatis-plus的使用示例(单表,一对多,多对多,条件
构造语句)
示例暂用三张表做演示:(t_user用户表、t_role角色表、t_user_role用户角色表)
以t_user表为例
(1)新建一个User表对应实体类:
使用@TableName("t_user")进行表名注解;
使用lombok插件的@Data注解在类上, 为类提供读写get/set属性, 此外还提供了
equals()、hashCode()、toString() 方法;
补充: lombok插件使用:
1):在pom.xml添加依赖
1 <dependency>
2 <groupId>org.projectlombok</groupId>
3 <artifactId>lombok</artifactId>
4 <version>1.18.2</version>
5 </dependency>
2):添加IDE工具对Lombok的支持
IDEA中引入Lombok支持如下: 点击File-- Settings设置界面,搜索安装
Lombok插件;实体类继承extends Model<User>,Model已经实现了序列化,不用再手动实现序列化;
1 /**
2 * 用户实体类
3 * @Author fansongsong
4 */
5 @Data
6 @TableName("t_user")
7 public class User extends Model<User> {
8 /**
9 * 主键
10 */
11 private String id;
12 /**
13 * 用户名
14 */
15 private String name;
16 /**
17 * 手机
18 */
19 private String mobile;
20 ...
21 /**
22 * 用户地址
23 */24 @TableField(exist = false)
25 @JsonProperty("address_name")
26 private String addressName;
27 }
这里几个注解需要注意,第一是@tableName("t_user"),它是指定与数据库表的关联,这里
的注解意味着你的数据库里应该有一个名为user的表与之对应,并且数据表的列名应该就是
User类的属性;
如果有需要,对于User类中有而user表中没有的属性需要加注解@TableField(exist =
false),表示排除User类中的属性;
如果有需要,把实体类字段名在以JSON形式返回前端时需要把该属性的名称序列化为另
外一个名称@JsonProperty("address_name")注解 ;
(2) 新建Dao层接口UserMapper:
dao接口即UserMapper需要继承mybatis-plus的Basemapper<User>接口,这样就能够使
用封装好的很多通用方法,
使用@Repository注明dao层,在Spring中配置扫描包地址,然后生成dao层的bean,之
后被注入到ServiceImpl中
1
2 /**
3 * 用户数据库控制层接口Mapper
4 * @Author fansongsong
5 */
6 @Repository
7 public interface UserMapper extends BaseMapper<User> {
8
9 /**
10 * 根据用户id获取用户角色组信息
11 * @param id 用户id
12 * @return UserRoleVO
13 */
14 UserRoleVO getUserRole(String id);
15 }
(3)新建UserMapping.xml配置文件:使用<mapper namespace="com.example.demo.user.mapper.UserMapper">与第二
步的UserMapper接口唯一绑定
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/myba
3 <mapper namespace="com.example.demo.user.mapper.UserMapper">
4
5 <resultMap id="BaseResultMap" type="com.example.demo.user.entity.User">
6 <result column="id" jdbcType="VARCHAR" property="id" />
7 <result column="name" jdbcType="VARCHAR" property="name" />
8 <result column="mobile" jdbcType="VARCHAR" property="mobile" />
9 <result column="create_time" property="createTime" />
10 <result column="modify_time" property="modifyTime" />
11 <result column="deleted" property="deleted" />
12 <result column="status" property="status" />
13 </resultMap>
14
15 <!-- 通用查询结果列 -->
16 <sql id="Base_Column_List">
17 id, name , mobile, create_time, modify_time, deleted, status
18 </sql>
19
20 </mapper>
(4)新建Service层类UserService:
继承mybatis-plus的 IService<User>接口
1 /**
2 * 用户服务类
3 * @author fansongsong
4 */
5 public interface IUserService extends IService<User> {
6 }
(5)新建ServiceImpl层类UserServiceImpl:UserServiceImpl类需要继承mybatis-plus的ServiceImpl<对应user实体Mapper, 对应user
实体> 并实现mybatis-plus的IUserService接口
使用@Service注明该类为服务实现层
使用@Resource注解将指定Bean默认按照ByName自动注入
使用@Override加在实现方法上是覆盖(override)或者重写(因为要实现这个接口里面
的所有方法),不加编译器也可以识别,加上增强代码的可读性
使用lombok的@Sl4j注解,进行log打印日志;
1 **
2 * 用户服务实现类
3 * @Author fansongsong
4 */
5 @Service
6 @Slf4j
7 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserServic
8
9 @Resource
10 UserMapper userMapper;
11
12 @Resource
13 IUserService userService;
14
15 @Resource
16 TUserRoleService userRoleService;
17
18 /**
19 * 查询用户角色v1(自定义sql)
20 * @param id 用户id
21 * @return UserRoleVO
22 */
23 @Override
24 public UserRoleVO userRoleV1(String id) {
25 //自定义sql根据用户id获取用户角色组信息
26 UserRoleVO result = userMapper.getUserRole(id);
27 log.info("UserRoleVO result msg:"+ result.getName());
28 return result;
29 }
30 }(6)新建Controller层类UserController:
使用@RestController注解标识该类为控制层;
使用@RequestMapping("/user")注解标识控制层的映射请求,也就是通过它来指定控制
器可以处理哪些URL请求;
使用@Resource、@Autowired注解将指定Bean默认按照ByName自动注入
使用@GetMapping("/get_user/{id}")支持请求类型为get的请求,一般用于获取资源请
求,值为请求路径;
使用@PostMapping("/create")支持请求类型为post的请求,一般用于向服务器提交资
源,值为请求路径;
使用@PutMapping("/update")支持请求类型为put的请求,一般用于向服务器更新资源,
值为请求路径;
使用@DeleteMapping("/delete_user/{id}")支持请求类型为delete的请求,一般用于向服
务器删除资源,值为请求路径;
使用@PathVariable(value = "id")注解,获取路径参数,如
@GetMapping("/get_user/{id}")请求获取路径中的{id}占位符的值;
使用@RequestBody注解,将JSON形式请求参数转化为相应的实体类
使用@RequestParam(value = "page_no", required = false, defaultValue = "1")注解,获
取请求体中的参数;
1 /**
2 * 用户控制层
3 * @Author fansongsong
4 */
5
6 @RestController
7 @RequestMapping("/user")
8 public class UserController {
9
10 @Resource
11 private IUserService userService;
12
13 //一对一
14 /**
15 * 根据用户id查询用户信息
16 * @param id 用户id
17 * @return ApiResponse
18 */19 @GetMapping("/get_user/{id}")
20 public ApiResponse getUser(@PathVariable(value = "id") String id) {
21 User user = userService.getUser(id);
22 return ApiResponse.success(user);
23 }
24 }
1:单表(CRUD)
1.1: 新增, UserServiceImpl.createUser()
1 userMapper.insert(user);或者
2 userService.save(user);
1.2: 修改, UserServiceImpl.updateUser()
1 userMapper.updateById(user);或者
2 userService.updateById(user);
1.3: 删除, UserServiceImpl.deleteUser()
1 userMapper.deleteById(id);或者
2 userService.removeById(id);
注意:mybatis-plus的删除默认是物理删除,如果需要逻辑删除要进行相关配置
1.3.1:application-test.yml配置,指定删除的value设为1,恢复的设为0
1 mybatis-plus:
2 global-config:
3 db-config:
4 logic-delete-value: 1 # 逻辑已删除值(默认为 1)
5 logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
1.3.2:在mybatis-plus-3.1.1版本之前需要在自己写的配置类中配置,后续版本直接跳
过,spring已经配好了
1 @Configuration2 public class MyConfig {
3 @Bean
4 public ISqlInjector SqlInjector(){
5 return new LogicSqlInjector();
6 }
7 }
1.3.3:先在数据库加deleted字段,对应的实体类deleted字段上加@TableLogic 注解标
识(对应字段类型推荐使用 Integer,Boolean,LocalDateTime),这就是告诉spring,我
要把这字段设为删除标志
1 /**
2 * 是否删除(0:未删,1:已删)
3 */
4 @TableLogic//逻辑删除
5 private Integer deleted;
1.4:查询
1.4.1: 单数据查询, UserServiceImpl.getUser()
1 // 一,Service提供的CRUD
2 // 1,根据 ID 查询
3 User user1 = userService.getById(id);
4
5 // 2,根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.
6 QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
7 userQueryWrapper.lambda().eq(User::getId,id);
8 User user2 = userService.getOne(userQueryWrapper);
9
10 // 3,根据 Wrapper,查询一条记录,throwEx(boolean),有多个 result 是否抛出异常
11 User user3 = userService.getOne(userQueryWrapper,false);
12
13 // 4,根据 Wrapper,查询一条记录,返回Map<String,Object>
14 Map<String,Object> user4 = userService.getMap(userQueryWrapper);
15
16 // 二,Mapper提供的CRUD
17
18 // 1,根据 entity 条件,查询一条记录19 QueryWrapper<User> queryWrapper = new QueryWrapper<>();
20 queryWrapper.lambda().eq(User::getId,id);
21 queryWrapper.lambda().eq(User::getDeleted, 0);
22 User user6 = userMapper.selectOne(queryWrapper);
23 // 2,根据 ID 查询
24 User user7 = userMapper.selectById(id);
1.4.2: 列表数据查询,UserServiceImpl.getListUser()
1 QueryWrapper<User> queryWrapper = new QueryWrapper<>();
2 List<User> result1 = userService.list(queryWrapper);
3 List<User> result2 = userMapper.selectList(queryWrapper);
2: 一对多查询
2.1: 使用自定义sql, UserServiceImpl.getUserRoleV1()
2.2: 使用mybatis-plus单表查询数据组装,UserServiceImpl.getUserRoleV2()
3. 多对多查询
3.1: 使用自定义sql,UserServiceImpl.getListUserRoleV2()
3.2: 使用mybatis-plus单表查询数据组装, UserServiceImpl.getListUserRoleV1()
4,分页插件PageHelper
官方文档:https://pagehelper.github.io/docs/howtouse/
配置:引入分页插件
在 pom.xml 中添加如下依赖:
1 <!-- 分页插件 -->
2 <dependency>
3 <groupId>com.github.pagehelper</groupId>
4 <artifactId>pagehelper</artifactId>
5 <version>5.1.0</version>
6 </dependency>
如何在代码中使用
在实现类使用PageHelper.startPage(pageNo, pageSize);进行分页
1 //每页的大小为pageSize,查询第pageNo页的结果
2 PageHelper.startPage(pageNo, pageSize);3 //执行查询语句
4 List<User> result = userService.list(queryWrapper);
在Controller使用new PageInfo<>(userList)进行包装返回前端
1 /**
2 * 根据筛选条件查询用户列表
3 * @param pageNo 当前第几页
4 * @param pageSize 每页显示条数
5 * @param mobile 手机号
6 * @param name 用户名
7 * @return List<User>
8 */
9 @GetMapping("/list_user")
10 public ApiResponse listUser(
11 @RequestParam(value = "page_no", required = false, defaultValue = "1") int pageNo
12 @RequestParam(value = "page_size", required = false, defaultValue = "5") int page
13 @RequestParam(value = "mobile", required = false) String mobile,
14 @RequestParam(value = "name", required = false) String name) {
15 List<User> userList = userService.listUser(pageNo,pageSize,mobile,name);
16 return ApiResponse.success(new PageInfo<>(userList));
17 }
五、MyBatis XML映射文件
学习文档:https://www.w3cschool.cn/mybatis/f4uw1ilx.html
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件
就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的
代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
1 resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
2 sql – 可被其他语句引用的可重用语句块。
3 insert – 映射插入语句
4 update – 映射更新语句
5 delete – 映射删除语句
6 select – 映射查询语句select 查询语句是 MyBatis 中最常用的元素之一:
1 <select id="selectPerson" parameterType="int" resultType="hashmap">
2 SELECT * FROM PERSON WHERE ID = #{id}
3 </select>
Select 常用属性描述:
1,XML映射文件和Mapper.java文件的绑定是通过xml中的
<mapper namespace = "Mapper类的完全限定名">
1 <mapper namespace="com.example.demo.user.mapper.UserMapper">
属性
描述
id
在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterTyp
e
将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 Typ
默认值为 unset。
resultType
从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包
resultType 或 resultMap,但不能同时使用。
resultMap
外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话
使用 resultMap 或 resultType,但不能同时使用。2. xml中sql通过标签的属性id="getUserRole"和映射的Mapper.java进行唯一绑定
insert,update 和 delete 语句的示例:
1
2 <insert id="insertAuthor">
3 insert into Author (id,username,password,email,bio)
4 values (#{id},#{username},#{password},#{email},#{bio})
5 </insert>
6
7 <update id="updateAuthor">
8 update Author set
9 username = #{username},10 password = #{password},
11 email = #{email},
12 bio = #{bio}
13 where id = #{id}
14 </update>
15
16 <delete id="deleteAuthor">
17 delete from Author where id = #{id}
18 </delete>
19
六,MyBatis 动态SQL
使用MyBatis动态SQL进行不同条件拼接 SQL 语句,拼接的时候要确保不能忘了必要的空
格,还要注意省掉列名列表最后的逗号等。
常用的动态 SQL 元素:
if
choose (when, otherwise)
trim (where, set)
foreach
1,if
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。比如:
1 <select id="getUserRoleList" resultMap="roleList" >
2 select
3 <include refid="Get_User_Role_List"/>
4 from t_user tu
5 left join t_user_role tur on tur.user_id = tu.id
6 left join t_role tr on tr.id = tur.role_id
7 <where>
8 tu.deleted = 0
9 <if test="roleId != null and roleId != ''">
10 and tr.id = #{roleId}11 </if>
12 <if test="mobile != null and mobile != ''">
13 and tu.mobile = #{mobile}
14 </if>
15 </where>
16 </select>
动态的通过"roleId"和"mobile"两个条件进行数据筛选,那个参数不为空就执行那个条件语句
2,choose (when, otherwise)
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis
提供了 choose 元素,例如这次变为提供了"title"就按"title"查找,提供了"author"就
按"author"查找,若两者都没有提供,就返回所有符合条件的结果
1 <select id="findActiveBlogLike"
2 resultType="Blog">
3 SELECT * FROM BLOG WHERE state = ‘ACTIVE’
4 <choose>
5 <when test="title != null">
6 AND title like #{title}
7 </when>
8 <when test="author != null and author.name != null">
9 AND author_name like #{author.name}
10 </when>
11 <otherwise>
12 AND featured = 1
13 </otherwise>
14 </choose>
15 </select>
4,trim (where, set)
一般常用在update 语句,set 元素可以被用于动态包含需要更新的列,而舍去其他的。比
如:
1 <update id="updateAuthorIfNecessary">
2 update Author3 <set>
4 <if test="username != null">username=#{username},</if>
5 <if test="password != null">password=#{password},</if>
6 <if test="email != null">email=#{email},</if>
7 <if test="bio != null">bio=#{bio}</if>
8 </set>
9 where id=#{id}
10 </update>
5,foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比
如:
1 <select id="selectPostIn" resultType="domain.blog.Post">
2 SELECT *
3 FROM POST P
4 WHERE ID in
5 <foreach item="item" index="index" collection="list"
6 open="(" separator="," close=")">
7 #{item}
8 </foreach>
9 </select>
同时也可以使用foreach来进行批量插入数据(注意:虽然Mybatis 对动态语句没有数量上
的限制,由于Mysql 对语句的长度有限制,默认是 4M,如果要进行大数据量批处理时,
尽量先把数据进行list切分,在进行批量插入操作)
代码示例:UserServiceImpl.createBatchSaveUser()
1 <!-- 批量保存sql -->
2 <insert id="batchSave" parameterType="java.util.List" >
3 INSERT INTO t_user (
4 `id`,
5 `name`,
6 `mobile`,
7 `create_time`,
8 `modify_time`,
9 `deleted`,
10 `status`,11 `age`
12 )
13 VALUES
14 <foreach collection="list" index="index" item="item" separator=",">
15 (
16 #{item.id},
17 #{item.name},
18 #{item.mobile},
19 #{item.createTime},
20 #{item.modifyTime},
21 #{item.deleted},
22 #{item.status},
23 #{item.age}
24 )
25 </foreach>
26 </insert>
对于批量数据操作mybatis-plus也有相关支持
1 userService.saveBatch(userList);
2 userService.saveOrUpdateBatch(userList);