springboot2.4.4整合mybatis

  • 一、搭建工程
  • 二、使用mybatis进行数据库操作
  • 三、测试运行
  • 四、总结



springboot目前已成为javaweb的主流开发框架,它就像一个万能胶,只要拉取相关依赖的starter,我们只需要做少量配置就能做到开箱即用。


mybatis是国内比较流行的持久层框架,即支持注解类型开发也支持xml类型开发,同时支持动态sql,非常灵活好用,spring也对该框架进行了适配,今天这篇博客的内容就是介绍如何使用springboot集成mybatis。

好啦,不罗嗦了正文开始!!!

一、搭建工程

  • maven工程大家就自己建,我这里就不罗嗦了,下面为工程的pom文件,大家将该文件复制到自己的pom中,拉取相关依赖(电脑必须有网络
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>quartz-job</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-quartz</artifactId>
         </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!-- <dependency>
             <groupId>org.springframework.session</groupId>
             <artifactId>spring-session-data-redis</artifactId>
         </dependency>
 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
       <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <version>3.32.3.2</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.13</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • 在resource文件夹下创建application.yml及application-dev.yml配置文件
    application.yml
server:
  port: 8080
spring:
  profiles:
    active: dev
#数据库配置splite数据库
#syx:
#  database:
#    url: jdbc:sqlite:D:/env/sqlite/sqlite-tools-win32-x86-3350500/sqlite-tools/mydb.db
#    driver: org.sqlite.JDBC
#    userName:
#    passwd:
#    validationQuery:
#    initSize: 3
#    minIdle: 3
#    maxActive: 10
#    checkTable: false
#    maxWaitTime: 60000
#    evictionRunTime: 60000
#    minEvictionIdleTime: 300000
#    keepAlive: true
#    testWhileIdle: true
#    testOnBorrow: true
#    testOnReturn: false
#    poolPreparedStatement: true
#    maxPoolPreparedStatementSizePerConnection: 20
#    validateQueryTimeOut: 3

#数据库配置mysql数据库
syx:
  database:
    url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
    driver: com.mysql.cj.jdbc.Driver
    userName: xxxx
    passwd: xxx
    validationQuery: select 1 from dual
    initSize: 3
    minIdle: 3
    maxActive: 10
    checkTable: false
    maxWaitTime: 60000
    evictionRunTime: 60000
    minEvictionIdleTime: 300000
    keepAlive: true
    testWhileIdle: true
    testOnBorrow: true
    testOnReturn: false
    poolPreparedStatement: true
    maxPoolPreparedStatementSizePerConnection: 20
    validateQueryTimeOut: 3

这里我把数据库的配置单独抽取为一个配置类,其中的一些参数在配置类中有注释。

application-dev.yml

mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml  #mapper文件的路径

#showSql
logging:
  level:
    com:
      syx:
        dao: debug

dev的配置文件比较简单,主要是指定mybatis的mapper.xml文件的位置。

  • 数据库配置类,主要是为了绑定application.yml中的数据库配置。
package com.syx.microapplication.base;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @date: 2022-03-10 23:04
 * <p>数据源配置参数</p>
 */
@Component
@ConfigurationProperties(prefix = "syx.database")
public class DataSourceConfigProperty {

    private String url;

    private String driver;

    private String userName;

    private String passwd;

    private String validationQuery = "select 1 from dual";

    //连接池初始大小
    private String initSize = "3";

    //最小连接数
    private String minIdle = "3";

    //最大连接数
    private String maxActive ="10";

    //是否开启表的初始化检查
    private boolean checkTable = false;

    //获取连接的最大等待时间单位为毫秒
    private long maxWaitTime;

    //空闲检测时间单位为毫秒
    private long evictionRunTime;

    //连接在池中最小生存时间单位毫秒
    private long minEvictionIdleTime;

    //
    private boolean keepAlive;

    private boolean testWhileIdle;

    //获取连接时是否检测连接有效
    private boolean testOnBorrow;

    //连接归还时是否检测连接有效
    private boolean testOnReturn;

    //是否缓存PrepareStatement
    private boolean poolPreparedStatement;

    //每个连接的  PrepareStatement缓存大小
    private int maxPoolPreparedStatementSizePerConnection;

    //连接检测超时设置
    private int validateQueryTimeOut;

    public String getUrl() {
        validate(url);
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDriver() {
        validate(driver);
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public String getValidationQuery() {
        return validationQuery;
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }

    public String getInitSize() {
        return initSize;
    }

    public void setInitSize(String initSize) {
        this.initSize = initSize;
    }

    public String getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(String minIdle) {
        this.minIdle = minIdle;
    }

    public String getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(String maxActive) {
        this.maxActive = maxActive;
    }

    public boolean isCheckTable() {
        return checkTable;
    }

    public void setCheckTable(boolean checkTable) {
        this.checkTable = checkTable;
    }

    public long getMaxWaitTime() {
        return maxWaitTime;
    }

    public void setMaxWaitTime(long maxWaitTime) {
        this.maxWaitTime = maxWaitTime;
    }

    public long getEvictionRunTime() {
        return evictionRunTime;
    }

    public void setEvictionRunTime(long evictionRunTime) {
        this.evictionRunTime = evictionRunTime;
    }

    public long getMinEvictionIdleTime() {
        return minEvictionIdleTime;
    }

    public void setMinEvictionIdleTime(long minEvictionIdleTime) {
        this.minEvictionIdleTime = minEvictionIdleTime;
    }

    public boolean isKeepAlive() {
        return keepAlive;
    }

    public void setKeepAlive(boolean keepAlive) {
        this.keepAlive = keepAlive;
    }

    public boolean isTestWhileIdle() {
        return testWhileIdle;
    }

    public void setTestWhileIdle(boolean testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }

    public boolean isTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public boolean isTestOnReturn() {
        return testOnReturn;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public boolean isPoolPreparedStatement() {
        return poolPreparedStatement;
    }

    public void setPoolPreparedStatement(boolean poolPreparedStatement) {
        this.poolPreparedStatement = poolPreparedStatement;
    }

    public int getMaxPoolPreparedStatementSizePerConnection() {
        return maxPoolPreparedStatementSizePerConnection;
    }

    public void setMaxPoolPreparedStatementSizePerConnection(int maxPoolPreparedStatementSizePerConnection) {
        this.maxPoolPreparedStatementSizePerConnection = maxPoolPreparedStatementSizePerConnection;
    }

    public int getValidateQueryTimeOut() {
        return validateQueryTimeOut;
    }

    public void setValidateQueryTimeOut(int validateQueryTimeOut) {
        this.validateQueryTimeOut = validateQueryTimeOut;
    }

    private void validate(String val){
        if(val == null || "".equals(val)){
            throw new IllegalArgumentException("数据库参数配置异常...");
        }
    }

    @Override
    public String toString() {
        return "DataSourceConfigProperty{" +
                "url='" + url + '\'' +
                ", driver='" + driver + '\'' +
                ", userName='" + userName + '\'' +
                ", passwd='" + passwd + '\'' +
                ", validationQuery='" + validationQuery + '\'' +
                ", initSize='" + initSize + '\'' +
                ", minIdle='" + minIdle + '\'' +
                ", maxActive='" + maxActive + '\'' +
                ", checkTable=" + checkTable +
                ", maxWaitTime=" + maxWaitTime +
                ", evictionRunTime=" + evictionRunTime +
                ", minEvictionIdleTime=" + minEvictionIdleTime +
                ", keepAlive=" + keepAlive +
                ", testWhileIdle=" + testWhileIdle +
                ", testOnBorrow=" + testOnBorrow +
                ", testOnReturn=" + testOnReturn +
                ", poolPreparedStatement=" + poolPreparedStatement +
                ", maxPoolPreparedStatementSizePerConnection=" + maxPoolPreparedStatementSizePerConnection +
                ", validateQueryTimeOut=" + validateQueryTimeOut +
                '}';
    }
}
  • 应用配置,该配置主要指定了组件扫描范围及mybayis的dao路径
package com.syx.microapplication.base;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @date: 2022-03-11 00:15
 * <p></p>
 */
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(AppConfig.COMPONENT_SCAN)
@MapperScan(AppConfig.MAPPER_SCAN)
public class AppConfig {

    //包扫描路径
    protected static final String COMPONENT_SCAN = "com.syx";

    //mybatis的dao路径
    protected static final String MAPPER_SCAN = "com.syx.**.dao";
}
  • 数据源配置,本应用使用的是druid数据源
package com.syx.microapplication.base;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * @date: 2022-03-10 23:01
 * <p>数据源配置</p>
 */
@Configuration
@EnableTransactionManagement
@ConditionalOnClass(DataSource.class)
public class DataSourceConfig {

    @Autowired
    private DataSourceConfigProperty dataSourceConfigProperty;


    @Bean
    @Primary
    public DruidDataSource dataSource(){
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(dataSourceConfigProperty.getUrl());
        druidDataSource.setDriverClassName(dataSourceConfigProperty.getDriver());
        druidDataSource.setUsername(dataSourceConfigProperty.getUserName());
        druidDataSource.setPassword(dataSourceConfigProperty.getPasswd());
        druidDataSource.setInitialSize(Integer.parseInt(dataSourceConfigProperty.getInitSize()));
        druidDataSource.setMinIdle(Integer.parseInt(dataSourceConfigProperty.getMinIdle()));
        druidDataSource.setMaxActive(Integer.parseInt(dataSourceConfigProperty.getMaxActive()));
        druidDataSource.setMaxWait(dataSourceConfigProperty.getMaxWaitTime());
        druidDataSource.setTimeBetweenEvictionRunsMillis(dataSourceConfigProperty.getEvictionRunTime());
        druidDataSource.setMinEvictableIdleTimeMillis(dataSourceConfigProperty.getMinEvictionIdleTime());
        druidDataSource.setTestWhileIdle(dataSourceConfigProperty.isTestWhileIdle());
        druidDataSource.setTestOnBorrow(dataSourceConfigProperty.isTestOnBorrow());
        druidDataSource.setTestOnReturn(dataSourceConfigProperty.isTestOnReturn());
        druidDataSource.setValidationQuery(dataSourceConfigProperty.getValidationQuery());
        return druidDataSource;
    }


    /**
     * druid监控平台
     * @return
     */
    @Bean
    public ServletRegistrationBean<StatViewServlet> servletRegistrationBean(){
        ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>();
        StatViewServlet servlet = new StatViewServlet();
        registrationBean.setServlet(servlet);
        registrationBean.setName("druidView");
        registrationBean.setLoadOnStartup(2);
        List<String> urlMapping = new ArrayList<>();
        urlMapping.add("/druid/*");
        registrationBean.setUrlMappings(urlMapping);
        return registrationBean;
    }
}
  • 启动类
package com.syx.microapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;

/**
 * @date: 2022-03-10 23:49
 * <p></p>
 */
@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {
        SpringApplication.run(MainApp.class,args);
    }
}

二、使用mybatis进行数据库操作

到目前为止,咱们的工程就搭建完毕了,接下来咱们就创建实体类、mybatis的dao以及mapper.xml文件。

  • 创建实体类
package com.syx.web.entity;

import lombok.Data;

@Data
public class Company {

    private int id;

    private String name;

    private int age;

    private String address;

    private float salary;
}
  • 实体类对应的数据表
CREATE TABLE `company` (
  `ID` int(11) NOT NULL,
  `NAME` varchar(40) DEFAULT NULL,
  `AGE` int(11) DEFAULT NULL,
  `ADDRESS` char(40) DEFAULT NULL,
  `SALARY` double DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
--插入一条模拟数据
INSERT INTO `mydb`.`company` (`ID`, `NAME`, `AGE`, `ADDRESS`, `SALARY`) VALUES ('1', 'zs', '11', 'china', '200110');
  • 创建mybatis的dao接口(一定要在@MapperScan注解指定的目录下创建)
package com.syx.web.dao;

import com.syx.web.entity.Company;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface CompanyDao {
    List<Company> findAll();
    Company findById(@Param("id") int id);
}
  • 创建dao对应的mapper.xml文件**(需要在 mapper-locations指定的目录下创建)**
<?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.syx.web.dao.CompanyDao">

    <resultMap id="CompanyResultMap" type="com.syx.web.entity.Company">
        <result column="ID"  property="id" />
        <result column="NAME"  property="name" />
        <result column="AGE"  property="age" />
        <result column="ADDRESS"  property="address" />
        <result column="SALARY"  property="salary" />

    </resultMap>
    
    <select id="findAll" resultMap="CompanyResultMap">
        select * from company
    </select>


    <select id="findById"  resultMap="CompanyResultMap">
        SELECT * FROM COMPANY
        <where>
            id=#{id}
        </where>
    </select>
</mapper>

mapper中标签的id要与dao中的方法名对应。

三、测试运行

package com.syx;

import com.syx.microapplication.MainApp;
import com.syx.web.dao.CompanyDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @date: 2022-03-12 19:06
 * <p></p>
 */
@SpringBootTest(classes = MainApp.class)
public class TestDao {
    @Autowired
    CompanyDao companyDao;
    @Test
    public void func3() {
        System.out.println(companyDao.findAll());
    }
}

spitngboot集成mysql springboot集成mybatis过程_spring

四、总结

springboot集成mybatis中我们做的配置有三处:
1、配置druid数据源(持久层框架依赖数据源)
2、指定@MapperScan注解扫描的包路径
3、指定mapper-locations的路径

大家看完整个过程是不是发现很简单,这就是springboot的自动装配的优势,其中最主要的一个类就是MybatisAutoConfiguration ,这个类帮我们完成了很多配置工作,包括注入数据源,初始化sqlSessionFactory等。。。

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration implements InitializingBean {}

大家有兴趣的可以自行学习该类的源码,从中可以了解springboot的自动装配原理。