SpringBoot整合Mybatis

SpringBoot整合Mybatis

相关地址

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

mybatis-plus官网:https://baomidou.com/

druid:https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

druid-spring-boot-starter:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

pageHelper: https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md

版本关系说明

引入依赖可能就需要考虑版本对应关系

其中mybatis和springboot的版本关系可以在https://start.spring.io/选择myatis相关依赖确定,

druid的版本没有找到说明,找个最新的吧,

pageHelper的版本参考器官方示例,这个地址由版本对应关系:https://github.com/pagehelper/pagehelper-spring-boot

mybatis-plus的话,其启动器已经包含了mybatis,只需要考虑和springboot的关系即可,而这个似乎没有找到

我本地是spring boot 2.6.11 版本

mybatis

依赖

        <!--druid 数据库连接池相关依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.15</version>
        </dependency>

        <!--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>
            <scope>runtime</scope>
        </dependency>

配置项

基础配置
#数据源
spring:
  datasource:
    username: root
    password: Jeol@1201
    # allowMultiQueries表示支持执行;间隔的多个sql nullCatalogMeansCurrent=true返回指定库涉及的表
    url: jdbc:mysql://kube.sry1201.cn:32306/test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 使用的连接池的类型
    type: com.alibaba.druid.pool.DruidDataSource
    # druid-spring-boot-starter 配置项 DruidAbstractDataSource中可以找到一些配置的默认值
    druid:
      # 初始化连接的个数
      initial-size: 10
      # 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请。
      min-idle: 10
      # 最大连接数
      max-active: 20
      # 获取连接的最大等待时长
      max-wait: 5000
      # 连接空闲时间超过了多长时间,配合testWhileIdle使用
      timeBetweenEvictionRunsMillis: 60000
      # 检测连接时执行的sql
      validationQuery: SELECT 1 FROM DUAL
      #建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
      testWhileIdle: true
      #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      testOnBorrow: false
      #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      testOnReturn: false
      # 连接保持空闲而不被驱逐的最小时间 默认1800000
      min-evictable-idle-time-millis: 600000
      # 连接保持空闲而不被驱逐的最大时间 默认25200000
      max-evictable-idle-time-millis: 900000
仅作记录
# 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
spring.datasource.druid.pool-prepared-statements=true
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=50
pom配置
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>

xml放置在resources下

mybatis:
  # 如果你的xml文件放在resouces目录下,你可以尝试这么配置,然后很显然,你需要以Mapper.xml结尾
  mapper-locations: classpath*:**/*Mapper.xml
  # 配置后xml返回的resultType中就不用写全限定类名,直接写类名就行,可以不配置
  type-aliases-package: cn.sry1201.*.model

否则报错如下

Invalid bound statement (not found): cn.sry1201.demo2.mapper.UserMapper2.selectAll

druid记录sql脚本日志

      # 自己配置监控统计拦截的filter
      filter:
        stat:
          #开启慢sql日志
          log-slow-sql: true
          # 超过2s认为是慢sql
          slow-sql-millis: 2000
          # druid统计(状态监控),默认开启
          enabled: true
          db-type: mysql
        # 日志监控,使用slf4j 进行日志输出

参考:https://blog.csdn.net/u012129558/article/details/124923444

  
    <appender name = "slow-sql"  class="ch.qos.logback.core.FileAppender">
        <!-- 日志文件保存路径 -->
        <file>${logHome}/slow-sql/slow-sql.log</file>
        <!-- 格式-->
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>


		<!-- com.alibaba.druid.filter.stat.StatFilter 输出SQL脚本-->
        <logger name="com.alibaba.druid.filter.stat.StatFilter" level="ERROR" additivity="false">
            <appender-ref ref="slow-sql" />
        </logger>

慢sql的认定时间调小一点就行了

druid监控界面

配置

#数据源
spring:
  datasource:
    username: root
    password: Jeol@1201
    # allowMultiQueries表示支持执行;间隔的多个sql
    url: jdbc:mysql://kube.sry1201.cn:32306/test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 使用的连接池的类型
    type: com.alibaba.druid.pool.DruidDataSource
    # druid-spring-boot-starter 配置项 DruidAbstractDataSource中可以找到一些配置的默认值
    druid:
      #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall,slf4j
      # 自己配置监控统计拦截的filter
      filter:
        stat:
          #开启慢sql日志
          log-slow-sql: true
          # 超过2s认为是慢sql
          slow-sql-millis: 2000
          # druid统计(状态监控),默认开启
          enabled: true
          db-type: mysql
        # 日志监控,使用slf4j 进行日志输出
        slf4j:
          enabled: true
          statement-log-error-enabled: true
          statement-create-after-log-enabled: false
          statement-close-after-log-enabled: false
          result-set-open-after-log-enabled: false
          result-set-close-after-log-enabled: false
      ########## 配置WebStatFilter,用于采集web关联监控的数据 ##########
      web-stat-filter:
        enabled: true                   # 启动 StatFilter
        url-pattern: /*                 # 过滤所有url
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" # 排除一些不必要的url
        session-stat-enable: true       # 开启session统计功能
        session-stat-max-count: 1000    # session的最大个数,默认100
      ########## 配置StatViewServlet(监控页面),用于展示Druid的统计信息 ##########
      stat-view-servlet:
        enabled: true                   # 启用StatViewServlet
        # http://localhost:8004/druid
        url-pattern: /druid/*           # 访问内置监控页面的路径,内置监控页面的首页是/druid/index.html
        reset-enable: false              # 不允许清空统计数据,重新计算
        login-username: root            # 配置监控页面访问密码
        login-password: 123
        allow: 127.0.0.1           # 允许访问的地址,如果allow没有配置或者为空,则允许所有访问
        deny:                                        # 拒绝访问的地址,deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝

两个实用的idea mybatis插件

在线的话直接安装

离线下载界面 :https://plugins.jetbrains.com/

Mybatis-log-plugin : 可以打开一个专门记录sql执行日志的界面,而且是最终执行的sql

Free-idea-mybatis:支持从mapper接口跳转到mapper.xml文件,这个插件还集成了mybatis-generator-gui,不过我没用过

直接搜索商店的话似乎名称有点对应不上, 可以大致看看其中文描述,安装好了之后是这样的

mybatis-generator-gui

官方:https://github.com/zouzg/mybatis-generator-gui/wiki/Usage-Guide

基于单个表,生成一些增删改查,批量,的xml示例,映射对象,接口等,主要是有一个前端的ui界面,操作方便,当然idea有些插件也有这个功能

安装问题

问题,似乎不能连接我8.0的mysql数据库,直接在打包号的lib目录下换驱动,连接成功后显示的表不对劲

下载后,修改DbType,驱动类,连接属性nullCatalogMeansCurrent=true,驱动包名

public enum DbType {

    MySQL("com.mysql.cj.jdbc.Driver", "jdbc:mysql://%s:%s/%s?useUnicode=true&useSSL=false&characterEncoding=%s&nullCatalogMeansCurrent=true", "mysql-connector-java-8.0.30.jar"),
    

删除其resouces -> lib目录下的5.0的mysql驱动,换成8.0的驱动

遵循官方文档操作,将app内的内容复制出来到单独的文件夹

git clone https://github.com/astarring/mybatis-generator-gui
cd mybatis-generator-gui
mvn jfx:jar
cd target/jfx/app/

编辑以个启动脚本start.bat放在复制出来的目录就可以了

:: java -jar mybatis-generator-gui.jar
start javaw -jar  mybatis-generator-gui.jar

我一般习惯比在外部生成再复制进项目

pageHelper使用

这是一个支持分页查询的框架

依赖

版本随意了,我没找到对应的文档,这里直接使用最新版本,不过似乎都对应maven中央仓库上面的说明都是对应boot2.7.5版本,没治

        <!-- 分页插件 springboot 2.x版本-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.5</version>
        </dependency>

基础用法1

大致是我们执行PageHelper.startPage后的第一个查询sql会被分页,然后将查询sql转成PageInfo对象,即可获取分页信息。

    @RequestMapping("/test1")
    public PageInfo getAllUser(@RequestParam Integer pageNum,@RequestParam Integer pageSize){
        //两个参数固定是,pageNum,pageSize,可以传入对象,或map,但是对象中属性必须包含pageNum,pageSize,map同理
        PageHelper.startPage(pageNum,pageSize);
        List<User> all = userMapper3.findAll();
        PageInfo pageInfo = new PageInfo<>(all);
        return pageInfo;
    }

返回的数据如下

{
    "total": 183,
    "list": [
        {
            "id": 1,
            "name": "毕淑儒",
            "py": "BSR"
        },
        {
            "id": 2,
            "name": "蔡兴熙",
            "py": "CXX"
        },
        {
            "id": 3,
            "name": "曾三杰",
            "py": "ZSJ"
        }
    ],
    "pageNum": 1,
    "pageSize": 3,
    "size": 3,
    "startRow": 1,
    "endRow": 3,
    "pages": 61,
    "prePage": 0,
    "nextPage": 2,
    "isFirstPage": true,
    "isLastPage": false,
    "hasPreviousPage": false,
    "hasNextPage": true,
    "navigatePages": 8,
    "navigatepageNums": [
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8
    ],
    "navigateFirstPage": 1,
    "navigateLastPage": 8
}

但是显然大部分数据否没什么用,我们实际使用中,可以在service业务代码中添加 PageHelper.startPage,然后在同一的返回结果类中定义方法统一处理查询sql返回的list对象,简略如下,然后大致就返回了前端需要的一下分页数据

    public static <T> ResponseResult<T> pageSuccess(List<?> data) {
        ResponseResult<T> responseResult = new ResponseResult<>();
        PageInfo pageInfo = new PageInfo<>(data);
        Map<String, Object> result = new HashMap<>(8);
        result.put(PAGE_NUM, pageInfo.getPageNum());
        result.put(PAGE_SIZE, pageInfo.getPageSize());
        result.put(TOTAL_PAGE, pageInfo.getPages());
        result.put(TOTAL, (int) pageInfo.getTotal());
        result.put(LIST, pageInfo.getList());
        responseResult.setCode(SUCCESS);
        responseResult.setMessage(SUCCESS_MSG);
        responseResult.setData((T) result);
        responseResult.setSuccess(true);
        return responseResult;
    }

使用注意

1、注意其分页只针对PageHelper.startPage之后执行的第一个查询sql

2、PageHelper默认是在执行的sql 尾部加上limit ,复杂的语句则select count(0) from (执行的查询) limit, 如果查询语句复杂,我们的limit用在某个查询的主表上再去关联其他表,显然效率会更高一点,所以还是需要会写手动的分页

配置项

@Configuration
public class PageHelperConfiguration {

    /**
     * 配置mybatis的分页插件PageHelperProperties

     */
    @Bean
    @Primary
    public PageHelperProperties pageHelper() {
        PageHelperProperties pageHelperProperties = new PageHelperProperties();
        pageHelperProperties.setAutoRuntimeDialect(Boolean.TRUE);
        //启用合理化时,如果pageNum <1 会查询第一页,如果pageNum > pages会查询最后一页
        pageHelperProperties.setReasonable(Boolean.TRUE);
        //默认值为false,当该参数设置为true时,如果pageSize=0或者RowBounds.limit=0就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是Page类型)
        pageHelperProperties.setPageSizeZero(Boolean.TRUE);
//        pageHelperProperties.setParams("count=countSql"); # 默认就是
        return pageHelperProperties;
    }
}

当然你也可以通过配置文件的方式配置,以pagehelper开头即可,具体请查看这个类的属性

@ConfigurationProperties(
    prefix = "pagehelper"
)
public class PageHelperProperties extends Properties {

其他示例

参考官方文档吧,大致我是用不上

Mybatis Plus

大致是对于一下简单的sql,我们可以通过继承Mybatis Plus为我们提供的BaseMapper来进行实现,这样如果只是简单的增删改查,我们就不需要写xml和sql了,此外还提供分页插件,乐观锁插件,甚至还提供分布式数据库id的生成、字段值的自动填充,非法sql检查

当然对于复杂查询,也提供条件构造器来构建,不过我建议还是使用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 操作智能分析阻断,也可自定义拦截规则,预防误操作

依赖

引入了mybatis-plus-boot-starter之后,就不需要引入Mybatis相关依赖了

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

基础示例

具体可以执行那些操作,查看BaseMapper

@Mapper
public interface UserMapper extends BaseMapper<User> {
    
}

如果实体类名称不是表名下划线转驼峰,需要通过注解单独指定表名

同时还支持 @TableField @TableId

@Setter
@Getter
@TableName("sys_user")
public class User {

    private int    id;
    private String name;
    private String py;

}

    @Resource
    private UserMapper userMapper;

    //测试Mybatis@select注解
    @RequestMapping("/test1")
    public User getAllUser(){
        User user = userMapper.selectById(1);
        return user;
    }

分页插件

@Configuration
@MapperScan("cn.sry1201.*.mapper")
public class MybatisPlusConfig {

    /**
     * mybatis plus 分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}
    @RequestMapping("/test2")
    public Page getAllUser2(){

        Page<User> page = new Page<>(2, 3);
        userMapper.selectPage(page, null);
        System.out.println("当前页数据:"+page.getRecords());
        System.out.println("总分页数量:"+page.getPages());
        System.out.println("总记录数量:"+page.getTotal());
        System.out.println("是否有下一页:"+page.hasNext());
        System.out.println("是否有上一页:"+page.hasPrevious());
        return page;
    }
{
    "records": [
        {
            "id": 4,
            "name": "常元琴",
            "py": "CYQ"
        },
        {
            "id": 5,
            "name": "陈栋芬",
            "py": "CDF"
        },
        {
            "id": 6,
            "name": "陈宁婷",
            "py": "CNZ"
        }
    ],
    "total": 183,
    "size": 3,
    "current": 2,
    "orders": [],
    "optimizeCountSql": true,
    "searchCount": true,
    "countId": null,
    "maxLimit": null,
    "pages": 61
}

关联信息

  • 关联的主题:
  • 上一篇:
  • 下一篇:
  • image: 20221120/1
  • 转载自:
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值