SpringBoot中整合MyBatis

网友投稿 234 2022-11-22


SpringBoot中整合MyBatis

MyBatis 框架相信大家都用过,虽然 MyBatis 可以直接在 xml 中通过 SQL 语句操作数据库,很是灵活。但正其操作都要通过 SQL 语句进行,就必须写大量的 xml 文件,很是麻烦。于是 MyBatis-Plus 应运而生,作为 MyBatis 的增强工具,更是为我们开发效率得到了质的飞跃。

一、简介

1、MyBatis

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

官方文档:

https://mybatis.org/mybatis-3/zh/index.html

2、MyBatis-Plus

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

官方文档:

https://mybatis.plus/guide/

二、开发前戏

1、引入 MyBatis-Plus

在 pom.xml 文件中引入 MyBatis-Plus 所需依赖

com.baomidou

mybatis-plus-boot-starter

3.3.1

com.baomidou

mybatis-plus-generator

3.3.1.tmp

org.freemarker

freemarker

mysql

mysql-connector-java

runtime

freemarker 作为 MyBatis-Plus 自动生成代码时作为模板使用,还可选用 velocity 作为模板

org.apache.velocity

velocity-engine-core

2.2

本次我们选用 freemarker 作为模板

2、配置信息

在 application.yml 文件中,配置 mybatis-plus 的信息

# mybatis配置

mybatis-plus:

# xml文件路径

mapper-locations: classpath:mapper/*.xml

# 实体类路径

type-aliases-package: com.zyxx.sbm.entity

configuration:

# 驼峰转换

map-underscore-to-camel-case: true

# 是否开启缓存

cache-enabled: false

# 打印sql

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

# 全局配置

global-config:

# 数据库字段驼峰下划线转换

db-column-underline: true

# id自增类型(数据库id自增)

id-type: 0

我们主要配置了:

xml 文件的存放位置

实体类的存放位置

开启驼峰转换原则

开启缓存

打印 sql 日志

id 自增策略,有多种策略,如下:

/**

* 数据库ID自增

*/

AUTO(0),

/**

* 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)

*/

NONE(1),

/**

* 用户输入ID

*

该类型可以通过自己注册自动填充插件进行填充

*/

INPUT(2),

/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */

/**

* 分配ID (主键类型为number或string),

* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)

*

* @since 3.3.0

*/

ASSIGN_ID(3),

/**

* 分配UUID (主键类型为 string)

* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))

*/

ASSIGN_UUID(4);

MyBatis-Plus 默认的是推特的“雪花算法”,但是这样生成的主键 id 会比较长,本次我们选择数据库自增策略

我们还需要在项目启动类加上

@MapperScan("com.zyxx.sbm.mapper")

@ComponentScan(basePackages = {"com.zyxx"})

扫描我们 mapper 包下面的文件,有时你会发现不在启动类当前包下面的文件无法扫描,于是加上第二个注解,扫描其他文件

3、自动生成代码类

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;

import com.baomidou.mybatisplus.generator.AutoGenerator;

import com.baomidou.mybatisplus.generator.InjectionConfig;

import com.baomidou.mybatisplus.generator.config.*;

import com.baomidou.mybatisplus.generator.config.po.TableInfo;

import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;

import java.util.List;

import java.util.Scanner;

/**

* 代码生成器

*

* @Author Lizhou

*/

public class CodeGenerator {

/**

*

* 读取控制台内容

*

*/

public static String scanner(String tip) {

Scanner scanner = new Scanner(System.in);

StringBuilder help = new StringBuilder();

help.append("请输入" + tip + ":");

System.out.println(help.toString());

if (scanner.hasNext()) {

String ipt = scanner.next();

if (StringUtils.isNotEmpty(ipt)) {

return ipt;

}

}

throw new MybatisPlusException("请输入正确的" + tip + "!");

}

/**

* 自动生成代码

*/

public static void main(String[] args) {

// 代码生成器

AutoGenerator mpg = new AutoGenerator();

// TODO 全局配置

GlobalConfig gc = new GlobalConfig();

String projectPath = System.getProperty("user.dir");

// 生成文件的输出目录【默认 D 盘根目录】

gc.setOutputDir(projectPath + "/src/main/java");

gc.setAuthor("lizhou");

// 是否打开输出目录

gc.setOpen(false);

// controller 命名方式,注意 %s 会自动填充表实体属性

gc.setControllerName("%sController");

// service 命名方式

gc.setServiceName("%sService");

// serviceImpl 命名方式

gc.setServiceImplName("%sServiceImpl");

// mapper 命名方式

gc.setMapperName("%sMapper");

// xml 命名方式

gc.setXmlName("%sMapper");

// 开启 swagger2 模式

gc.setSwagger2(true);

// 是否覆盖已有文件

gc.setFileOverride(true);

// 是否开启 ActiveRecord 模式

gc.setActiveRecord(true);

// 是否在xml中添加二级缓存配置

gc.setEnableCache(false);

// 是否开启 BaseResultMap

gc.setBaseResultMap(true);

// XML columList

gc.setBaseColumnList(false);

// 全局 相关配置

mpg.setGlobalConfig(gc);

// TODO 数据源配置

DataSourceConfig dsc = new DataSourceConfig();

dsc.setUrl("jdbc:mysql://127.0.0.1:3306/sbm?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=true&characterEncoding=UTF-8");

dsc.setDriverName("com.mysql.jdbc.Driver");

dsc.setUsername("root");

dsc.setPassword("123456");

mpg.setDataSource(dsc);

// TODO 包配置

PackageConfig pc = new PackageConfig();

// 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名

pc.setParent("com.zyxx.sbm");

// Entity包名

pc.setEntity("entity");

// Service包名

pc.setService("service");

// Service Impl包名

pc.setServiceImpl("service.impl");

mpg.setPackageInfo(pc);

// TODO 自定义配置

InjectionConfig cfg = new InjectionConfig() {

@Override

public void initMap() {

// to do nothing

}

};

// 输出文件配置

List focList = new ArrayList<>();

focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {

@Override

public String outputFile(TableInfo tableInfo) {

// 自定义输入文件名称

return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper.xml";

}

});

// 自定义输出文件

cfg.setFileOutConfigList(focList);

mpg.setCfg(cfg);

mpg.setTemplate(new TemplateConfig().setXml(null));

// TODO 策略配置

StrategyConfig strategy = new StrategyConfig();

// 数据库表映射到实体的命名策略,驼峰原则

strategy.setNaming(NamingStrategy.underline_to_camel);

// 字数据库表字段映射到实体的命名策略,驼峰原则

strategy.setColumnNaming(NamingStrategy.underline_to_camel);

// 实体是否生成 serialVersionUID

strategy.setEntitySerialVersionUID(false);

// 是否生成实体时,生成字段注解

strategy.setEntityTableFieldAnnotationEnable(true);

// 使用lombok

strategy.setEntityLombokModel(true);

// 设置逻辑删除键

strategy.setLogicDeleteFieldName("del_flag");

// TODO 指定生成的bean的数据库表名

strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));

// 驼峰转连字符

strategy.setControllerMappingHyphenStyle(true);

mpg.setStrategy(strategy);

// 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!

mpg.setTemplateEngine(new FreemarkerTemplateEngine());

mpg.execute();

}

}

我们需要改变的就是:

数据库的连接信息,地址,用户,密码

controller、service、mapper、xml 等文件的命名规则

生成文件 controller、service、mapper、xml 文件的存放位置

数据库与实体类之间的一些策略配置等

三、开发进行中

1、创建数据表

我们创建一个用户信息表 user_info

drop table if exists user_info;

/*==============================================================*/

/* Table: user_info */

/*==============================================================*/

create table user_info

(

id bigint(20) not null auto_increment comment '主键id',

account varchar(32) comment '账号',

password varchar(32) comment '密码',

name varchar(32) comment '姓名',

phone varchar(11) comment '电话',

avatar varchar(255) comment '头像',

sex tinyint(1) comment '性别(0--未知1--男2--女)',

create_time datetime comment '创建时间',

create_user bigint(20) comment '创建人',

status tinyint(1) default 0 comment '状态(0--正常1--冻结)',

del_flag tinyint(1) default 0 comment '删除状态(0,正常,1已删除)',

primary key (id)

)

type = InnoDB;

alter table user_info comment '用户信息表';

2、生成代码

我们利用刚刚创建的自动生成代码类,生成关于 user_info 数据表的 controller、service、mapper、xml、entity 等文件

生成方法:

运行自动生成代码类中的 main 方法

在控制台输入表名 user_info

生成的文件就自动放在我们配置的包下面

3、代码鉴赏

UserInfo.java 文件

import com.baomidou.mybatisplus.annotation.*;

import com.baomidou.mybatisplus.extension.activerecord.Model;

import com.zyxx.common.annotation.Dict;

import io.swagger.annotations.ApiModel;

import io.swagger.annotations.ApiModelProperty;

import lombok.Data;

import lombok.EqualsAndHashCode;

import lombok.experimental.Accessors;

import java.io.Serializable;

/**

*

* 用户信息表

*

*

* @author lizhou

* @since 2020-07-06

*/

@Data

@EqualsAndHashCode(callSuper = false)

@Accessors(chain = true)

@TableName("sys_user_info")

@ApiModel(value="SysUserInfo对象", description="用户信息表")

public class UserInfo extends Model {

@ApiModelProperty(value = "ID")

@TableId(value = "id", type = IdType.AUTO)

private Long id;

@ApiModelProperty(value = "登录账号")

@TableField("account")

private String account;

@ApiModelProperty(value = "登录密码")

@TableField("password")

private String password;

@ApiModelProperty(value = "姓名")

@TableField("name")

private String name;

@ApiModelProperty(value = "电话")

@TableField("phone")

private String phone;

@ApiModelProperty(value = "头像")

@TableField("avatar")

private String avatar;

@ApiModelProperty(value = "性别(0--未知1--男2--女)")

@TableField("sex")

private Integer sex;

@ApiModelProperty(value = "状态(0--正常1--冻结)")

@TableField("status")

private Integer status;

@ApiModelProperty(value = "创建时间")

@TableField("create_time")

private String createTime;

@ApiModelProperty(value = "创建人")

@TableField("create_user")

private Long createUser;

@ApiModelProperty(value = "删除状态(0--未删除1--已删除)")

@TableField("del_flag")

@TableLogic

private Integer delFlag;

@Override

protected Serializable pkVal() {

return this.id;

}

}

@TableName(“sys_user_info”) ,标注表名

Model,继承了 Model 抽象类,并实现了序列化

@ApiModelProperty(value = “ID”),注释,这是在自动生成代码类中配置了 // 开启 swagger2 模式 gc.setSwagger2(true);才会生成的

@TableId(value = “id”, type = IdType.AUTO),表明了主键自增策略

@TableField(“account”),标注了数据库中对应的字段

@TableLogic,逻辑删除字段,表示我们在调用删除方法时,数据库并不会物理删除,而是被改变状态,查询的时候,默认不查询已被删除的数据,可以配置逻辑删除值,默认0未删除,1已删除

pkVal(),方法用于插入返回自增id

UserInfoMapper.java 文件

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.zyxx.sbm.entity.UserInfo;

/**

*

* 用户信息表 Mapper 接口

*

*

* @author lizhou

* @since 2020-07-06

*/

public interface UserInfoMapper extends BaseMapper {

}

继承了 BaseMapper 抽象类,使得有了 CRUD 的基本方法

UserInfoMapper.xml 文件

namespace,命名空间,指明这个 xml 文件属于哪一个 mapper 文件

BaseResultMap,结果集,我们可以定义不同的结果集,来返回我们所需要的数据

UserInfoService.java 文件

import com.baomidou.mybatisplus.extension.service.IService;

import com.zyxx.common.utils.LayTableResult;

import com.zyxx.common.utils.ResponseResult;

import com.zyxx.sbm.entity.UserInfo;

/**

*

* 用户信息表 服务类

*

*

* @author lizhou

* @since 2020-07-06

*/

public interface UserInfoService extends IService {

}

继承了 IService 接口,使得有了 CRUD 的方法

相比 mapper,还有了批量操作的方法

UserInfoServiceImpl.java 文件

import com.zyxx.sbm.entity.UserInfo;

import com.zyxx.sbm.service.UserInfoService;

import org.springframework.stereotype.Service;

import java.util.List;

/**

*

* 用户信息表 服务实现类

*

*

* @author lizhou

* @since 2020-07-06

*/

@Service

public class UserInfoServiceImpl extends ServiceImpl implements UserInfoService {

}

UserInfoController.java 文件

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.*;

/**

*

* 用户信息表 前端控制器

*

*

* @author lizhou

* @since 2020-07-06

*/

@Controller

@RequestMapping("/user-info")

public class UserInfoController {

}

四、开始使用

1、分页查询

我们在 service 的实现类中写一个 分页查询用户的方法,listUserInfo()

@Override

public void listUserInfo(Integer page, Integer limit, UserInfo UserInfo) {

QueryWrapper queryWrapper = new QueryWrapper<>();

if (StringUtils.isNotBlank(sysUserInfo.getName())) {

queryWrapper.like("name", sysUserInfo.getName());

}

queryWrapper.orderByDesc("ceLQkSbreate_time");

IPage iPage = page(new Page<>(page, limit), queryWrapper);

long total = iPage.getTotal();

List list = iPage.getRecords();

}

我们传入了查询条件:根据用户名称查询,再根据用户的注册时间倒序排序,最后分页查询

iPage.getTotal(),就得到了总数量,为 long 型

iPage.getRecords(),就得到了结果集,为 List 集合

我们还可以使用 lambda 的方式来写查询条件,例如:

queryWrapper.lambda().eq(SysUserInfo::getName, sysUserInfo.getName());

这样,就能避免写数据库字段的时候写错了

2、分页插件

注意:这时候,我们查询数据,发现分页并没有起作用,我们还需要配置 MyBatis-Plus 的分页插件

创建 MybatisPlusConfig.java 文件

package com.zyxx.common.mybatis;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.transaction.annotation.EnableTransactionManagement;

/**

* mybatis配置

*

* @Author Lizhou

*/

@EnableTransactionManagement

@Configuration

public class MybatisPlusConfig {

/**

* 分页插件

*/

@Bean

public PaginationInterceptor paginationInterceptor() {

return new PaginationInterceptor();

}

}

这时候,我们的分页就正常了,分页默认从1开始,所以不用考虑page = (page-1)*limit 才能使用,1-20的数据,就传入 1,20,20-40的数据就传入 2,20 就可以了

其它的增删改查的方法也是使用很方便的,如果涉及到多表联查,我们还是在 xml 文件中写 sql 吧

五、总结

无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件- - 构造器,满足各类使用需求

支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错

支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更- - 有超多自定义配置等您来使用

内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库

内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java Tree结构数据中查找匹配节点方式
下一篇:SpringBoot中整合Shiro实现权限管理的示例代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~