如果文章中代码不便于阅读,请使用电脑查看或点击阅读原文。
在 Spring Boot整合MyBatis连接数据库 这篇文章中,我们已经可以使用Spring Boot整合MyBatis来连接数据库,但随着使用,我们发现,MyBatis还是稍微有点复杂,那有没有更加简单的方式来操作数据库呢,我们惊奇的发现了MyBatis Plus。
0 开发环境
-
JDK:1.8
-
Spring Boot:2.1.1.RELEASE
-
MySQL:5.7.13
1 引入依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.4</version></dependency><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope></dependency><!--lombok--><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope></dependency>
2 引入数据源
application.yml 增加如下配置信息
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&serverTimezone=GMT%2B8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver#mybatis-plus: mapper-locations: classpath:mapper/*.xml #对应mapper映射xml文件所在路径 type-aliases-package: cn.wbnull.springbootdemo.entity #对应实体类路径
3 测试
3.1 新建数据库表
CREATE SCHEMA `test` DEFAULT CHARACTER SET utf8mb4 ;CREATE TABLE `test`.`user` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, PRIMARY KEY (`id`));INSERT INTO `test`.`user` (`name`) VALUES ('张三');INSERT INTO `test`.`user` (`name`) VALUES ('李四');INSERT INTO `test`.`user` (`name`) VALUES ('王五');INSERT INTO `test`.`user` (`name`) VALUES ('周六');
3.2 创建实体类
package cn.wbnull.springbootdemo.entity;import lombok.Data;@Datapublic class User { private int id; private String name;}
3.3 创建Mapper
package cn.wbnull.springbootdemo.mapper;import cn.wbnull.springbootdemo.entity.User;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.springframework.stereotype.Repository;@Repositorypublic interface UserMapper extends BaseMapper<User> {}
3.4 创建映射文件
在 resources 目录下新建 mapper 文件夹,用于存放MyBatis Plus映射文件
<?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.wbnull.springbootdemo.mapper.UserMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="cn.wbnull.springbootdemo.entity.User"> <id column="id" property="id"/> <result column="name" property="name"/> </resultMap> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> id, name </sql></mapper>
3.5 创建Service
package cn.wbnull.springbootdemo.service;import cn.wbnull.springbootdemo.entity.User;import cn.wbnull.springbootdemo.mapper.UserMapper;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class UserService { @Autowired private UserMapper userMapper; public String add(String name) { User user = new User(); user.setName(name); userMapper.insert(user); return "操作成功"; } public List<User> query() { LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); return userMapper.selectList(queryWrapper); } public String update(int id, String name) { LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.set(User::getName, name); updateWrapper.eq(User::getId, id); userMapper.update(updateWrapper); return "操作成功"; } public String delete(int id) { LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(User::getId, id); userMapper.delete(queryWrapper); return "操作成功"; }}
3.6 创建Controller
package cn.wbnull.springbootdemo.controller;import cn.wbnull.springbootdemo.entity.User;import cn.wbnull.springbootdemo.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("user")public class UserController { @Autowired public UserService userService; @PostMapping(value = "add") public String add(@RequestParam(value = "name") String name) { return userService.add(name); } @PostMapping(value = "query") public List<User> query() { return userService.query(); } @PostMapping(value = "update") public String update(@RequestParam(value = "id") int id, @RequestParam(value = "name") String name) { return userService.update(id, name); } @PostMapping(value = "delete") public String delete(@RequestParam(value = "id") int id) { return userService.delete(id); }}
3.7 项目启动类
增加@MapperScan,扫描mapper
package cn.wbnull.springbootdemo;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@MapperScan("cn.wbnull.springbootdemo.mapper")public class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); }}
3.8 测试
使用Postman进行测试,输出结果如下
3.8.1 select

3.8.2 insert

我们查下数据库,并再用postman请求


3.8.3 update

数据库中成功更新

3.8.4 delete

数据库中成功删除

截至这里,Spring Boot已经成功整合MyBatis Plus并连接上了数据库,且测试正常。
对比发现,我们使用LambdaQueryWrapper来操作数据库会特别方便,
并且,在我们实际开发中,如果存在大量数据库表,我们依旧可以使用Generator来自动生成代码
4 条件构造器 QueryWrapper
上面 3.5 中,我们创建的Service类中,使用了QueryWrapper简化SQL,其基本用法可参考官方文档:https://baomidou.com/pages/10c804/
以下简单整理可供参考
| 函数名 | 说明 | 例子 |
|---|---|---|
| allEq | 全部eq(或个别isNull) | allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is nullallEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王' |
| eq | 等于 = | eq("name", "老王")--->name = '老王' |
| ne | 不等于 <> | ne("name", "老王")--->name <> '老王' |
| gt | 大于 > | gt("age", 18)--->age > 18 |
| ge | 大于等于 >= | ge("age", 18)--->age >= 18 |
| lt | 小于 < | lt("age", 18)--->age < 18 |
| le | 小于等于 <= | le("age", 18)--->age <= 18 |
| between | BETWEEN 值1 AND 值2 | between("age", 18, 30)--->age between 18 and 30 |
| notBetween | NOT BETWEEN 值1 AND 值2 | notBetween("age", 18, 30)--->age not between 18 and 30 |
| like | LIKE '%值%' | like("name", "王")--->name like '%王%' |
| notLike | NOT LIKE '%值%' | notLike("name", "王")--->name not like '%王%' |
| likeLeft | LIKE '%值' | likeLeft("name", "王")--->name like '%王' |
| likeRight | LIKE '值%' | likeRight("name", "王")--->name like '王%' |
| notLikeLeft | NOT LIKE '%值' | notLikeLeft("name", "王")--->name not like '%王' |
| notLikeRight | NOT LIKE '值%' | notLikeRight("name", "王")--->name not like '王%' |
| isNull | 字段 IS NULL | isNull("name")--->name is null |
| isNotNull | 字段 IS NOT NULL | isNotNull("name")--->name is not null |
| in | 字段 IN (value.get(0), value.get(1), ...)字段 IN (v0, v1, ...) | in("age",{1,2,3})--->age in (1,2,3)in("age", 1, 2, 3)--->age in (1,2,3) |
| notIn | 字段 NOT IN (value.get(0), value.get(1), ...)NOT IN (v0, v1, ...) | notIn("age",{1,2,3})--->age not in (1,2,3)notIn("age", 1, 2, 3)--->age not in (1,2,3) |
| inSql | 字段 IN ( sql语句 ) | inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3) |
| notInSql | 字段 NOT IN ( sql语句 ) | notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6)notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3) |
| groupBy | 分组:GROUP BY 字段, ... | groupBy("id", "name")--->group by id,name |
| orderByAsc | 排序:ORDER BY 字段, ... ASC | orderByAsc("id", "name")--->order by id ASC,name ASC |
| orderByDesc | 排序:ORDER BY 字段, ... DESC | orderByDesc("id", "name")--->order by id DESC,name DESC |
| orderBy | 排序:ORDER BY 字段, ... | orderBy(true, true, "id", "name")--->order by id ASC,name ASC |
| having | HAVING ( sql语句 ) | having("sum(age) > 10")--->having sum(age) > 10having("sum(age) > {0}", 11)--->having sum(age) > 11 |
| func | func 方法(主要方便在出现if...else下调用不同方法能不断链) | func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)}) |
| or | 拼接 OR | eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着') |
| and | AND 嵌套 | and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着') |
| nested | 正常嵌套 不带 AND 或者 OR | nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着') |
| apply | 拼接 sql | apply("id = 1")--->id = 1apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'") apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'") |
| last | 无视优化规则直接拼接到 sql 的最后 | last("limit 1") |
| exists | 拼接 EXISTS ( sql语句 ) | exists("select id from table where age = 1")--->exists (select id from table where age = 1) |
| notExists | 拼接 NOT EXISTS ( sql语句 ) | notExists("select id from table where age = 1")--->not exists (select id from table where age = 1) |
| QueryWrapper | ||
| select | 设置查询字段 | select("id", "name", "age")select(i -> i.getProperty().startsWith("test")) |
| UpdateWrapper | ||
| set | SQL SET 字段 | set("name", "老李头")set("name", "")--->数据库字段值变为空字符串set("name", null)--->数据库字段值变为null |
| setSql | 设置 SET 部分 SQL | setSql("name = '老李头'") |
5 代码生成器
5.1 引入依赖
<!-- 代码生成器 --><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.4</version></dependency><!-- 模板引擎 --><dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.3</version></dependency>
5.2 新建代码生成器类
代码生成器所有配置可参考官方文档:https://baomidou.com/pages/981406/
package cn.wbnull.springbootdemo.mybatis;import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;import com.baomidou.mybatisplus.generator.AutoGenerator;import com.baomidou.mybatisplus.generator.config.*;import com.baomidou.mybatisplus.generator.config.rules.DateType;import java.util.Collections;import java.util.Scanner;public class MybatisPlusGenerator { private static final String URL = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&serverTimezone=GMT%2B8"; private static final String USERNAME = "root"; private static final String PASSWORD = "root"; private static final String PACKAGE_PATH = System.getProperty("user.dir") + "/spring-boot-mybatis-plus/src/main/java"; private static final String RESOURCES_MAPPER_PATH = System.getProperty("user.dir") + "/spring-boot-mybatis-plus/src/main/resources/mapper/"; public static void main(String[] args) { DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(URL, USERNAME, PASSWORD) .build(); AutoGenerator autoGenerator = new AutoGenerator(dataSourceConfig); autoGenerator.global(globalConfig()); autoGenerator.packageInfo(packageConfig()); autoGenerator.strategy(strategyConfig()); autoGenerator.execute(); } private static GlobalConfig globalConfig() { return new GlobalConfig.Builder() .outputDir(PACKAGE_PATH) .author("null") .dateType(DateType.TIME_PACK) .commentDate("yyyy-MM-dd") .disableOpenDir() .build(); } private static PackageConfig packageConfig() { return new PackageConfig.Builder() .parent("cn.wbnull.springbootdemo") .pathInfo(Collections.singletonMap(OutputFile.xml, RESOURCES_MAPPER_PATH)) .build(); } private static StrategyConfig strategyConfig() { return new StrategyConfig.Builder() .addInclude(scanner().split(",")) .mapperBuilder() .enableBaseResultMap() .enableBaseColumnList() .build(); } public static String scanner() { Scanner scanner = new Scanner(System.in); String hint = "请输入数据库表名,多个表名使用英文逗号分隔:"; System.out.println(hint); if (scanner.hasNext()) { String ipt = scanner.next(); if (ipt != null && ipt.length() > 0) { return ipt; } } throw new MybatisPlusException("请输入正确的数据库表名"); }}
5.3 测试
5.3.1 新建数据库表
我们先新建一个数据库表,便于一会测试自动生成代码
CREATE TABLE `test`.`user_info` ( `id` INT NOT NULL AUTO_INCREMENT, `userCode` VARCHAR(20) NOT NULL, `userName` VARCHAR(45) NULL, `password` VARCHAR(40) NOT NULL, PRIMARY KEY (`id`));
5.3.2 测试
运行MybatisPlusGenerator,输入需要生成的表名

文件生成完成

生成文件如下

这样,对于大量的数据库表,我们就可以使用Generator来生成基本的代码,然后自己再添加其他所需要的代码即可。
CSDN:https://blog.csdn.net/dkbnull/article/details/136331111
本篇文章来源于微信公众号: 程序员null
微信扫描下方的二维码阅读本文

Comments NOTHING