springboot 整合 mybatis-plus

news2024/10/6 13:23:29

一.前言

        1. mybatis-plus是什么

        mybatis-plus是一个对mybati框架的拓展框架,它在mybatis框架基础上做了许多的增强,帮助我们快速的进行代码开发。目前企业开发中,使用mybati的项目基本会选择使用mybatis-plus来提升开发效率。

        2.官网地址:MyBatis-Plus 🚀 为简化开发而生

二.项目集成

        1. 项目中集成(示例用的springboot2.x+mysql)

        step1.引入依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.7</version>
</dependency>

        step2.配置数据源

spring: 
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.**.**:3306/rui
    username: root
    password: ******

        step3.启动类添加注解 @MapperScan 指向mapper接口所在包

@SpringBootApplication
@MapperScan("com.rui.mapper")
@EnableFeignClients(defaultConfiguration = MyFeignConfiguration.class)
public class AdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminServerApplication.class, args);
    }
}

        step4.定义实体类

        step5.编码测试:

(编码测试演示比较接近实际开发的代码,如果只是简单验证,用baseMapper就行了)

以下代码均为mybatis-plus提供的代码生成器生成的,如何使用在后续段落会讲,这里先看一下代码样子,眼熟以下

代码结构:

controller层:

@Slf4j
@RestController
@RequestMapping("/configInfo")
public class ConfigInfoController {

    @Autowired
    private IConfigInfoService configInfoService;

    @GetMapping("/list")
    public List<ConfigInfo>  listConfigs () {
        return configInfoService.list();
    }

}

service层:

        interface:

public interface IConfigInfoService extends IService<ConfigInfo> {

}

        impl:

** 注意,这里继承了一个ServiceImpl 它是mybatis-plus提供的类,帮我们完成许DB操作**

@Service
public class ConfigInfoServiceImpl extends ServiceImpl<ConfigInfoMapper, ConfigInfo> implements IConfigInfoService {

}

mapper层:

        mapper接口:

** 注意,我们的mapper实现了 BaseMapper ,它是mybatis-plus提供的接口,有常用的CRUD**

public interface ConfigInfoMapper extends BaseMapper<ConfigInfo> {

}

        mapper.xml: (其实就是空的,如果后面开始有自定义sql,需要这里写)

<?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="com.rui.mapper.ConfigInfoMapper">

</mapper>

        以上操作结束后,启动项目,postMan访问接口,发现可以正常访问数据库:

在测试环节,大家可以发现我的service和mapper都是空的,但是却可以调用list方法访问数据库。

其实,上面的编码中,我们在自己的业务Service中继承了抽象类ServiceImpl,ServiceImpl实现了IService这个接口中的方法,并定义了四个成员变量 baseMapper,entityClass, mapperClass,log,且这四个成员变量都是protected的,因此,在我们的业务Service中,我们可以直接调用IService的方法诸如saveAndUpdate,list,page等,也可以通过this.baseMapper 的方式来获取baseMapper对象,来调用baseMapper的方法

三.使用技巧

        1.理解mybatis-plus在代码中做的事情

        mybatis-plus为我们提供的最核心的功能其实就是对Mybatis的Mapper接口的增强,它提供了一个BaseMapper,一个mybatis的mapper接口继承了BaseMapper的话,就会被mybatis-plus进行增强,实现一系列的常用的数据库操。使用mybatis-plus最简单的办法其实就是引入mybatis-plus的依赖后,定义好Entity对象(实体对象),然后让mapper继承BaseMapper,最终我们使用baseMaper中的方法来进行开发。

        看一个使用baseMapper的例子:

        todo

        但是直接使用baseMaper的话,有许多操作我们还需要自己写代码,比如一些批量操作,如batchSave(批量插入)等。所以,mybatis-plus还提供了ServiceImpl,来帮我们实现这些。

        上面的编码中,我们在自己的业务Service中继承了抽象类ServiceImpl,ServiceImpl实现了IService这个接口中的方法,并定义了四个成员变量 baseMapper,entityClass, mapperClass,log,且这四个成员变量都是protected的,因此,在我们的业务Service中,我们可以直接调用IService的方法诸如saveAndUpdate,list,page等,也可以通过this.baseMapper 的方式来获取baseMapper对象,来调用baseMapper的方法。

        2.使用QueryWrapper进行查询

        以该service为例:

        QueryWrapper是我们工作中每天都啊哟使用的,场景非常多,我列出一些常见的场景,方便大家查阅

                1.1. 新增

        ConfigInfo configInfo = mockData();
        this.baseMapper.insert(configInfo);

                1.2. 删除

        LambdaQueryWrapper<ConfigInfo> configInfoQueryWrapper = new LambdaQueryWrapper<>();
        configInfoQueryWrapper.eq(ConfigInfo::getId, 500L);
        this.baseMapper.delete(configInfoQueryWrapper);

                1.3. 修改

        // 方法1 根据id更新,直接传入对象
        ConfigInfo configInfo = mockData();
        this.baseMapper.updateById(configInfo);

        //方法2 使用wrapper更新 set代表要修改的字段 eq是条件为相等的isi
        UpdateWrapper<ConfigInfo> configInfoUpdateWrapper = Wrappers.update();
        configInfoUpdateWrapper.set("appName","chengxuyuanA");
        configInfoUpdateWrapper.set("groupId", "groupA");
        configInfoUpdateWrapper.eq("id", 500L);
        this.baseMapper.update(configInfoUpdateWrapper);

                1.4. 查询

                列表查询

                        简单查询(简单的条件查询)

        // 查润groupId 为 5001的数据
        LambdaQueryWrapper<ConfigInfo> configInfoQueryWrapper = new LambdaQueryWrapper<>();
        configInfoQueryWrapper.eq(ConfigInfo::getGroupId, "5001");
        List<ConfigInfo> res = this.baseMapper.selectList(configInfoQueryWrapper);

                        复杂查询  (场景太多了,我就用一个包含 and, or, in ,between ,order by 的sql来表示一下用法)

        // select *
        // from config_info
        // where app_name like '%app%'
        //  and id between 1 and 50
        //  or (src_ip in ('1.0.1.1', '196.123.1.1', '0.0.0.0') and effect is not null)
        LambdaQueryWrapper<ConfigInfo> configInfoQueryWrapper = new LambdaQueryWrapper<>();
        configInfoQueryWrapper.like(ConfigInfo::getAppName, "app")
                        .between(ConfigInfo::getId, 1, 50);
        configInfoQueryWrapper.or(w->w.in(ConfigInfo::getSrcIp,srcips).isNotNull(ConfigInfo::getEffect));

                        分组聚合(其实这个一般不会用,考虑性能和优化,聚合的东西一般自己写sql)

        LambdaQueryWrapper<ConfigInfo> configInfoQueryWrapper = new LambdaQueryWrapper<>();
        configInfoQueryWrapper.groupBy(ConfigInfo::getGroupId);

        Long res = this.baseMapper.selectCount(configInfoQueryWrapper);

                分页查询

        Page page = new Page();
        page.setCurrent(1);
        page.setSize(10);

        LambdaQueryWrapper<ConfigInfo> configInfoQueryWrapper = new LambdaQueryWrapper<>();
        configInfoQueryWrapper.eq(ConfigInfo::getGroupId, "5001");
        IPage<ConfigInfo> pageData = this.page(page, configInfoQueryWrapper);

        3.自定义sql查询

                3.1.使用自定义sql

                和使用mybatis完全一样,这里不赘述了

                3.2.对自定义sql分页

                interface层

IPage<ConfigRation> selectUserPage(Page page, @Param("configration") ConfigRation configrationVo);

                同mybatis的正常使用,但是在第一个参数加上一个Page入参

        4.字段映射及一些注解使用技巧

                普通映射

                默认不需要注解,只要把数据库的字段的_去掉,换成小驼峰就行了

                如果需要对象属性名和数据库字段名称不同,可以用如下注解:

@TableField(value = "data_Source")
private String dataType;

                java对象的属性在数据库中不存在

@TableField(exist = false)
@Schema(description = "是否绑定告警通知规则,true是。false否")
private Boolean isBindNoticeRule;
                枚举映射

枚举注解@EnumValue,需要在枚举对象和java的实体类上都加:

public enum GenderEnum {
   
    MALE(0, "男"),
    FEMALE(1, "女");

    @EnumValue
    private final int code;
    private final String desc;

    GenderEnum(int code, String desc) {
   
        this.code = code;
        this.desc = desc;
    }
}
@TableName("user")
public class User {
   
    @TableId
    private Long id;

    @TableField("gender")
    @EnumValue
    private GenderEnum gender;

    // 省略其他属性和方法
}
                逻辑删除注解

逻辑删除需要进行一些配置:

step1:增加配置

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值
      logic-not-delete-value: 0 # 逻辑未删除值

step2:在实体类中使用 @TableLogic 注解

public class User {
    // 其他字段...

    @TableLogic
    private Integer deleted;
}
                多数据源注解

多数据源支持需要一个包  dynamic-datasource

step1:maven增加依赖

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>${version}</version>
</dependency>

step2:数据源配置:

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx)
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver

step3:使用 @DS 切换数据源

@Service
@DS("slave")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  @Override
  @DS("slave_1")
  public List selectByCondition() {
    return jdbcTemplate.queryForList("select * from user where age >10");
  }
}
                字段忽略注解
@TableField(exist = false)
private String companyname;

四.常用插件

       1.插件介绍

        介绍两个插件DataPermissionInterceptor, PaginationInnerInterceptor

        DataPermissionInterceptor:

        我们在开发中,很多项目有多租户,多组织的需求,不同租户和组织能看到的数据内容不同。假如业务数据我们用一个字段tenent_id区分不同租户的数据,那么我们希望开发者在编码时候,不需要刻意关注这个字段,正常写业务逻辑就好,有一个统一的拦截器能帮助我们在调用数据库时候把 tenent_id = {user_tenent_id} 这段sql加到查询语句中,DataPermissionInterceptor就是帮我们做这个事情的。

        实际开发中,基本涉及到多组织,多租户的项目都会使用这个插件。如果大家在开发中发现使用了mybatis-plus的项目默认拼接了一些sql,可以尝试搜索DataPermissionInterceptor来找一下加的地方。

        PaginationInnerInterceptor

        分页插件, 对于单一数据库类型来说,都建议配置该值,避免每次分页都去抓取数据库类型,使用方法很简单,直接new PaginationInnerInterceptor(dataType就好)

        2.实战使用

step1: 注册拦截器,加入了上面介绍的俩插件

@Configuration
public class MybatisAutoConfiguration implements WebMvcConfigurer {

	@Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor(@Autowired(required = false) DataPermissionHandler dataPermissionHandler) {
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
		if (dataPermissionHandler != null) {
			interceptor.addInnerInterceptor(new DataPermissionInterceptor(dataPermissionHandler));
		}
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
		return interceptor;
	}
}

 step2:DataPermissionHandler编码

public class DataPermissionHandler extends MultiDataPermissionHandler {
    @Override
    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
        // 在此处编写自定义数据权限逻辑
        try {
            String sqlSegment = "..."; // 数据权限相关的 SQL 片段
            return CCJSqlParserUtil.parseCondExpression(sqlSegment);
        } catch (JSQLParserException e) {
            e.printStackTrace();
            return null;
        }
    }
}

五.使用代码生成器

        关于代码生成器

        代码生成器在工作中其实很常用,所以我觉得不了解的道友还是需要了解一下。

        1.代码生成器配置

        我使用的mybatis-plus是3.5.7,低于3.5版本的话,可能略有不同

        step1:引入两个依赖包:

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!-- freemarker模板 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
            <version>3.1.2</version>
        </dependency>

       step2:创建一个java类,用来生成代码,我一般喜欢在项目中建一个dev文件夹,放一些开发工具

        结构如图:

代码:

public class CodeGenerator {

    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://192.168.**.**:3306/rui",
                        "root",
                        "******")
                .globalConfig(builder -> builder
                        .author("rui")
                        .outputDir(Paths.get(System.getProperty("user.dir")) +
                                "/services/admin-server" +
                                "/src/main/java")
                        .commentDate("yyyy-MM-dd")
                )
                .packageConfig(builder -> builder
                        .parent("com.rui")
                        .entity("entity")
                        .mapper("mapper")
                        .service("service")
                        .serviceImpl("service.impl")
                        .xml("mapper.xml")
                )
                .strategyConfig(builder -> builder
                        // 要生成代码的表名称,不加下面这行就是全库生成
                        .addInclude("config_info") 
                        .entityBuilder()
                        .enableLombok()
                )
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

}

        2.代码生成器使用

        直接右键执行即可,执行后就会在项目中生成对应文件。默认的模板controller,service中是没有方法的,可以自己配置一下模板,放一些和前端交互的CRUD。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1892072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习:预测评估8类指标

机器学习&#xff1a;8类预测评估指标 R方值、平均值绝对误差值MAE、均方误差MSE、均方误差根EMSE、中位数绝对误差MAD、平均绝对百分误差MAPE、可解释方差分EVS、均方根对数误差MLSE。 一、R方值 1、说明&#xff1a; R方值&#xff0c;也称为确定系数或拟合优度&#xff…

3099.力扣每日一题7/3 Java(击败100%)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 首先要解决如何…

MobileVitv1替换yolov8主干网络

一、原理介绍 MobileViT模型是为移动设备设计的轻量级、通用目的视觉变换器。它融合了卷积神经网络&#xff08;CNN&#xff09;和视觉变换器&#xff08;ViT&#xff09;的优势&#xff0c;旨在在保持高效性能的同时减少模型参数和降低延迟。以下是关于MobileViT模型的主要原理…

2024企业数据资产化及数据资产入表方案梳理

01 数据资产入表&#xff1a;是一个将组织的各类数据资产进行登记、分类、评估和管理的流程。 数据资产包括&#xff1a;客户信息、交易记录、产品数据、财务数据等。 做个比喻吧&#xff1a;数据资产入表就像是给公司的数据资产做“人口普查”—— ①找出公司有哪些数据找…

在uni-app使用vue3使用vuex

在uni-app使用vue3使用vuex 1.在项目目录中新建一个store目录&#xff0c;并且新建一个index.js文件 import { createStore } from vuex;export default createStore({//数据&#xff0c;相当于datastate: {count:1,list: [{name: 测试1, value: test1},{name: 测试2, value: …

【DataSophon】DataSophon1.2.1服务组件开启 kerberos

目录 一、DataSophon是什么 1.1 DataSophon概述 1.2 架构概览 1.3 设计思想 二、集成组件 三、环境准备 四、安装kerberos服务 4.1 Zookeeper 4.2 HDFS 4.3 HBase 4.4 YARN 4.5 hive 【DataSophon】大数据管理平台DataSophon-1.2.1安装部署详细流程-CSDN博客 【Da…

Qt中udp指令,大小端,帧头帧尾实际示例

前言 虽然QT中&#xff0c;udp发送和接收&#xff0c;其实非常简单&#xff0c;但是实际工作中&#xff0c;其实涉及到帧头帧尾&#xff0c;字节对齐&#xff0c;以及大小端序的问题。比如网络中&#xff0c;正规的一般都是大端序&#xff0c;而不是小端序&#xff0c;大多数的…

2024鲲鹏昇腾创新大赛集训营Ascend C算子学习笔记

异构计算架构&#xff08;CANN&#xff09; 对标英伟达的CUDA CuDNN的核心软件层&#xff0c;向上支持多种AI框架&#xff0c;向下服务AI处理器&#xff0c;发挥承上启下的关键作用&#xff0c;是提升昇腾AI处理器计算效率的关键平台。主要包括有各种引擎、编译器、执行器、算…

mac磁盘工具如何合并分区 macos 磁盘工具 无法抹除 磁盘管理软件哪个使用率最高

一、什么是NTFS格式分区 NTFS格式分区是微软公司开发的诸多文件系统中的一种。NTFS格式分区是一种文件系统&#xff0c;磁盘只有在安装了文件系统后才能被正常使用&#xff0c;文件系统的格式有非常多&#xff0c;常见的有FAT 32和NTFS。 作为常见文件系统&#xff0c;NTFS格式…

Conmi的正确答案——ESP32-C3开启安全下载模式

IDF版本&#xff1a;4.4.7 注意事项&#xff1a;一旦烧录“安全下载模式”&#xff0c;模组将无法被读取或清理&#xff0c;只能通过eclipse原项目烧录程序进行重新烧录&#xff0c;无法再烧录其他固件。 20240703110201——追加解法&#xff0c;暂时无法解安全下载模式 &…

Python数据分析-股票数据分析(GARCH模型)

一、研究背景 随着金融市场的不断发展和全球经济的日益复杂&#xff0c;市场波动性和风险管理成为投资者和金融机构关注的焦点。波动率是衡量市场风险的重要指标&#xff0c;准确预测和评估波动率对于资产定价、风险控制和投资决策具有重要意义。在金融时间序列分析中&#xf…

上海会议论坛可以邀请哪些媒体?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 上海会议论坛可以邀请的媒体包括电视媒体、报纸媒体、网络媒体、视频媒体以及专业的媒体邀约机构。具体介绍如下&#xff1a; 电视媒体&#xff1a;上海的第一财经频道和东方财经频道等&…

《python程序语言设计》2018版第5章第51题利用turtle画18x18的格子

05.51.01version 先从第一一个格子来做 turtle.right(45) turtle.circle(18, steps4) turtle.hideturtle() turtle.done()这个代码很简单的现实出格子的样式。 现在的问题是循环的话。首先角度45度怎么处理 随着45度一次一次迭代。他是应该转4590呢还是4545呢&#xff1f;&…

【Mac】Boxy SVG for Mac(矢量图编辑器)及同类型软件介绍

软件介绍 Boxy SVG 是一款功能强大的矢量图形编辑器&#xff0c;专门为 macOS 平台设计开发。它主要用于创建和编辑 SVG&#xff08;可缩放矢量图形&#xff09;文件&#xff0c;是设计师和开发者们制作矢量图形的理想工具。 以下是关于 Boxy SVG 的主要特点和功能&#xff1a…

权限维持Linux---监控功能Strace后门命令自定义Alias后门

免责声明:本文仅做技术交流与学习... 目录 监控功能Strace后门 1、记录 sshd 明文 监控 筛选查看 2、记录sshd私钥 命令自定义Alias后门 1、简单粗鲁实现反弹&#xff1a; 靶机替换命令 攻击机监听上线 2.升级(让命令正常) 将反弹命令进行base64编码 替换alias命令 …

使用本地部署的Hermes 2 Pro构建开放的LLM应用程序

之前我介绍了如何使用OpenAI最新的LLM GPT-4o&#xff0c;通过函数调用将实时数据引入到LLM。在这篇后续文章中我将介绍使用Hermes 2 Pro -Llama- 3 8B进行函数调用&#xff0c;这是一种由Nous Research开发的功能强大的LLM&#xff0c;基于Meta的Llama 3架构&#xff0c;有80亿…

解锁Diffusion Model: 初识Stable Diffusion、DALL-E、Imagen

------->更多内容&#xff0c;请移步“鲁班秘笈”&#xff01;&#xff01;<------- 扩散模型在生成高质量图像、视频、声音等方面表现突出。它们与物理学中的自然扩散过程相似而得名&#xff0c;自然扩散过程描述了分子如何从高浓度区域移动到低浓度区域。在机器学习的…

【Python】已解决:ModuleNotFoundError: No module named ‘cv2’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named ‘cv2’ 一、分析问题背景 在Python编程中&#xff0c;当你尝试导入一个不存在的模块时&#xff0c;会遇到ModuleNotFou…

公有链、私有链与联盟链:区块链技术的多元化应用与比较

引言 区块链技术自2008年比特币白皮书发布以来&#xff0c;迅速发展成为一项具有颠覆性潜力的技术。区块链通过去中心化、不可篡改和透明的方式&#xff0c;提供了一种全新的数据存储和管理方式。起初&#xff0c;区块链主要应用于加密货币&#xff0c;如比特币和以太坊。然而&…

Vue84-Vuex的工作原理与搭建开发环境

一、vuex工作原理 stats&#xff1a;是一个object对象&#xff0c;里面有很多key-value&#xff0c;存放的就是要操作的数据。mutations&#xff1a;是一个object对象&#xff0c;真正去操作stats的人。actions的作用&#xff1a;是一个object对象&#xff0c;当一个动作对应的…