SpringBoot 整合 MyBatis
介绍
mybatis是一个用Java编写的持久层框架,它使用ORM实现了结果集的封装。
ORM是Object Relational Mapping 对象关系映射。简单来说,就是把数据库表和实体类及实体类的属性对应起来,让开发者操作实体类就实现操作数据库表。
它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等烦杂过程。
而MyBatis Generator(简称MBG),如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的po类,xxxMapper.xml,xxxMapper.java文件,这显然需要花费巨大的精力,而且可能由于表字段太多,写错了而不知道也是可能的。
所以我们在实际开发中,一般使用逆向工程方式来自动生成所需的文件。
mybatis是目前很流行的持久层框架,其逆向工程更是大大缩减了我们的开发时间。所谓mybatis逆向工程,就是mybatis通过相应插件,根据我们设计好的数据表,针对单表自动生成pojo、mapper以及mapper.xml。
mybatis分页可以减少数据的处理量,分页的方式有两种:limit分页、PageHelper分页插件。
使用 Validator 校验参数,主要是用于检查程序代码中参数的有效性。
添加maven依赖
<!-- 集成mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- druid 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.12</version>
</dependency>
<!-- MyBatis Generator 逆向工程-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.1</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.3</version>
</dependency>
<!-- 校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
逆向工程
新增generatorConfig.xml文件
- 连接数据库的配置,包括数据名称,数据库用户名密码等配置
- 指定要生成代码的包名,包括实体类po的包名,mapper的包名等
- 指定数据库中哪些表需要生成文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="Mysql" targetRuntime="MyBatis3" defaultModelType="flat">
<!-- 自动检查关键字,为关键字增加反引号 -->
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!--覆盖生成XML文件-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />
<!-- 生成的实体类添加toString()方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!-- 不生成注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai"
userId="root"
password="123456">
<!--解决mysql驱动升级到8.0后不生成指定数据库代码的问题-->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- domain类的位置 -->
<javaModelGenerator targetProject="src\main\java"
targetPackage="com.example.demo.entity"/>
<!-- mapper xml的位置 -->
<sqlMapGenerator targetProject="src\main\resources"
targetPackage="mapper"/>
<!-- mapper类的位置 -->
<javaClientGenerator targetProject="src\main\java"
targetPackage="com.example.demo.mapper"
type="XMLMAPPER"/>
<!-- 指定数据库表,要生成哪些表,就写哪些表,要和数据库中对应,不能写错! -->
<table tableName="sys_user" domainObjectName="SysUser"/>
</context>
</generatorConfiguration>
一般新增的generatorConfig.xml文件都放在项目的 src/main/resources 下面新建一个 generator包里面。
执行generatorConfig.xml文件,生成代码
- 【方式一】安装插件
- 【方式二】java代码
注意点:
使用逆向工程时,最好新建一个工程,如果你在原来的工程中使用,也是可以的, 但是有一定的风险,因为mybatis是根据配置文件中配置的路径来生成的文件的,如果你工程中有相同名字的文件,那么就会被新生成的文件所覆盖。所以实际开发中, 我们一般新建一个工程,将生成的文件复制到自己的所需的工程中。
【方式一】安装插件(个人推荐)
<!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
</plugin>
操作步骤
打开编辑运行对话框点击【编辑配置】(图)
点击加号(+),并选择Maven
在运行那里输入指定字段【mybatis-generator:generate -e】
在名称那里自定义名称编写
最后点击应用和确定,就可以点击右侧的绿色小箭头运行了
【方式二】java代码
package com.example.test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MybatisGenerator {
public void testGenerator() throws Exception {
List<String> warnings = new ArrayList<>();
boolean overwrite = true;
//指定逆向工程配置文件
File configFile = new File("src/main/resources/generator/generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,callback,warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
MybatisGenerator generator = new MybatisGenerator();
generator.testGenerator();
}
}
直接运行main方法就行了!
最后,注意一下,生成什么表就在generatorConfig.xml文件里面放入什么表,已经生成的表,把注释或者删除就行了,以防重复生成。
mybatis的逆向工程实现起来其实是非常简单的,但是在不同情况下,要特别注意文件路径的问题。
其中,XxxExample.java只能实现简单条件增删改查,复杂的功能还需要自己编写sql代码来实现。
注意,在配置文件中配置对应生成文件的所在目录时,最好使用绝对路径
配置文件application.yml
基础的一些配置:
- 设置端口号
- 配置数据库连接
- 配置mybatis的mapper路径
- SQL打印日志
server:
port: 8087 # 重新设置端口号
spring:
datasource: #增加数据库链接
url: jdbc:mysql://localhost:3306/demo?characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai&allowMultiQueries=true
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis: #配置mybatis所有Mapper.xml所在的路径
mapper-locations: classpath:/mapper/**/*.xml
logging: #SQL日志打印
level:
com.example.demo.mapper: trace
在SpringBoot项目的启动类上面添加@MapperScan注解
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
简单的增删改查
【controller】
这里我没有用数据库表的实体类,是用了实体类的复制版本,在日常的开发当中,需求不一样,如果都用实体类来做,容易乱,为了清晰的区分,像【SysUserSaveReq 】代表新增和更新的参数配置,【SysUserQueryReq 】代表查询(含条件查询)分页数据的参数配置,我们会在ServiceImpl业务实现层去替换成数据库的实体类做增删改查。
package com.example.demo.controller;
import com.example.demo.dto.req.query.SysUserQueryReq;
import com.example.demo.dto.req.save.SysUserSaveReq;
import com.example.demo.dto.resp.PageResp;
import com.example.demo.dto.resp.SysUserResp;
import com.example.demo.service.SysUserService;
import com.example.demo.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/sys/user")
public class SysUserController {
@Autowired
private SysUserService sysUserService;
/**
* 新增 / 更新
* @param req
* @return
*/
@PostMapping("/save")
public Result toSave(@Valid @RequestBody SysUserSaveReq req){
int row = 0;
if(ObjectUtils.isEmpty(req.getUserId())){
row = sysUserService.toSave(req);
}else {
row = sysUserService.toUpdate(req);
}
if(row == 0){
return Result.error();
}
return Result.success();
}
/**
* 查询(含条件查询)
* @param req
* @return
*/
@GetMapping("/list")
public Result toList(@Valid SysUserQueryReq req){
PageResp<SysUserResp> pageResp = sysUserService.getList(req);
if(CollectionUtils.isEmpty(pageResp.getList())){
return Result.error();
}
return Result.success(pageResp);
}
/**
* 账号注销(逻辑删除)
* @param userId
* @return
*/
@PutMapping("/logout/{userId}")
public Result toLogout(@PathVariable Long userId){
int row = sysUserService.toLogout(userId);
if(row == 0){
return Result.error();
}
return Result.success();
}
}
【serviceImpl】
在业务实现层中的【SnowFlake 】类,是一种雪花算法的ID计算方式,【CopyUtil】类,是封装的对Object对象和List数据的复制方法,我们在复制对象的时候直接调用即可。
package com.example.demo.service.impl;
import com.example.demo.common.GlobalCommon;
import com.example.demo.dto.req.query.SysUserQueryReq;
import com.example.demo.dto.req.save.SysUserSaveReq;
import com.example.demo.dto.resp.PageResp;
import com.example.demo.dto.resp.SysUserResp;
import com.example.demo.entity.SysUser;
import com.example.demo.entity.SysUserExample;
import com.example.demo.mapper.SysUserMapper;
import com.example.demo.service.SysUserService;
import com.example.demo.utils.CopyUtil;
import com.example.demo.utils.SnowFlake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.List;
@Service
public class SysUserServiceImpl implements SysUserService {
@Autowired
private SnowFlake snowFlake;
@Autowired
private SysUserMapper sysUserMapper;
/**
* 新增
* @param req
* @return
*/
@Override
public int toSave(SysUserSaveReq req) {
SysUser sysUser = CopyUtil.copy(req, SysUser.class);
long id = snowFlake.nextId();
sysUser.setUserId(id);
sysUser.setCreateDate(new Date());
sysUser.setState(GlobalCommon.STATE);
sysUser.setDelFlag(GlobalCommon.DEL_FLAG);
int insert = sysUserMapper.insert(sysUser);
return insert;
}
/**
* 修改
* @param req
* @return
*/
@Override
public int toUpdate(SysUserSaveReq req) {
SysUser sysUser = CopyUtil.copy(req, SysUser.class);
sysUser.setUpdateDate(new Date());
int update = sysUserMapper.updateByPrimaryKeySelective(sysUser);
return update;
}
/**
* 查询(含条件查询)
* @param req
* @return
*/
@Override
public PageResp<SysUserResp> getList(SysUserQueryReq req) {
// 条件
SysUserExample example = new SysUserExample();
SysUserExample.Criteria criteria = example.createCriteria();
if(StringUtils.hasText(req.getUserName())){
criteria.andUserNameEqualTo(req.getUserName());
}
if(StringUtils.hasText(req.getNickName())){
criteria.andNickNameEqualTo(req.getNickName());
}
if(StringUtils.hasText(req.getPhone())){
criteria.andPhoneEqualTo(req.getPhone());
}
if(!ObjectUtils.isEmpty(req.getSex())){
criteria.andSexEqualTo(req.getSex());
}
if(!ObjectUtils.isEmpty(req.getState())){
criteria.andStateEqualTo(req.getState());
}
if(!ObjectUtils.isEmpty(req.getDelFlag())){
criteria.andDelFlagEqualTo(req.getDelFlag());
}
// 分页
PageHelper.startPage(req.getPage(),req.getSize());
// 查询
List<SysUser> users = sysUserMapper.selectByExample(example);
PageInfo<SysUser> pageInfo = new PageInfo<>(users);
// 复制
List<SysUserResp> respList = CopyUtil.copyList(users, SysUserResp.class);
// 返回
PageResp<SysUserResp> pageResp = new PageResp<>();
pageResp.setTotal(pageInfo.getTotal());
pageResp.setList(respList);
return pageResp;
}
/**
* 账号注销(逻辑删除)
* @param userId
* @return
*/
@Override
public int toLogout(Long userId) {
SysUser sysUser = new SysUser();
sysUser.setUserId(userId);
sysUser.setState(GlobalCommon.NO_STATE);
sysUser.setDelFlag(GlobalCommon.N0_DEL_FLAG);
sysUser.setUpdateDate(new Date());
int update = sysUserMapper.updateByPrimaryKeySelective(sysUser);
return update;
}
}
运行测试
总结
以上就是 SpringBoot 整合 Mybatis 的一些内容,如果你觉得有帮助,请o( ̄▽ ̄)d点赞收藏!多多支持!!!