【Spring Boot课程】14.整合Mybatis

小编 2026-06-05 阅读:828 评论:0
简介 MyBatis前身是apache的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBat...

简介

MyBatis前身是apache的一个开源项目iBatis,2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis2013年11月迁移到Github。

他是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。他消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装,支持简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

这一节,我们将学习如何将mybatis整合到我们的项目中,辅助数据库操作。

演示项目

创建项目

同样采用SpringInitializer创建项目,选择如下模块:

  • web 作为web启动
  • MySQL 作为数据库驱动
  • JDBC 为我们自动配置数据源(可不选择,mybatis会依赖)
  • MyBatis 数据访问框架

引入mybatis只需引入依赖

pom.xml
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

从其artifactId我们可以了解到,这不是官方包。

配置基本环境信息

我们按整合jdbc与数据源那一章节配置的方式将基础环境配置好。

application.yml

server:
  port: 8086
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://10.21.1.47:3306/joyblack?characterEncoding=utf8&serverTimezone=GMT
    driver-class-name: com.mysql.cj.jdbc.Driver
    initialization-mode: always
    sql-script-encoding: utf-8
    schema:
      - classpath:sql/joyblack.sql

然后倒入我们创建数据库以及倒入数据的sql文件,为了偷懒,我们统一将其放在schema逻辑中。该脚本创建了两张表user以及department,分别代表用户信息以及用户所在的部门信息,并导入了3个冒险者用户以及2个工会部门。

sql/joyblack.sql

/*
Navicat MySQL Data Transfer

Source Server         : docker
Source Server Version : 50505
Source Host           : 10.21.1.47:3306
Source Database       : joyblack

Target Server Type    : MYSQL
Target Server Version : 50505
File Encoding         : 65001

Date: 2018-12-20 09:45:44
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `department`
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `id` int(11) NOT NULL,
  `department_name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of department
-- ----------------------------
INSERT INTO `department` VALUES (\'1\', \'乡下冒险者公会\');
INSERT INTO `department` VALUES (\'2\', \'城市冒险者公会\');

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `user_name` varchar(20) NOT NULL,
  `login_name` varchar(20) NOT NULL,
  `deparment_id` int(11) NOT NULL DEFAULT 1,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (\'1\', \'阿库娅\', \'akuya\', \'1\');
INSERT INTO `user` VALUES (\'2\', \'克里斯汀娜\', \'crustina\', \'1\');
INSERT INTO `user` VALUES (\'3\', \'惠惠\', \'huihui\', \'1\');

我们接下来跑一下应用程序,初始化数据库信息。为了运行快速一点,之后我们应该把配置文件中的schema:- classpath:sql/joyblack.sql给注释掉,下次就不要在初始化了。

创建实体Bean

接下来我们创建对应的Bean,关联数据库表实体。

bean/User.class

package com.zhaoyi.mbweb.bean;

public class User {
    private Integer id;
    private String loginName;
    private String userName;
    private Integer departmentId;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getUserName() {
        return userName;
    }

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

    public Integer getDepartmentId() {
        return departmentId;
    }

    public void setDepartmentId(Integer departmentId) {
        this.departmentId = departmentId;
    }
}


bean/Department.class

package com.zhaoyi.mbweb.bean;

public class Department {
    private Integer id;
    private String departmentName;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }
}

准备工作完成了,我们可以准备使用mybatis了。

接下来我们就可以使用mybatis提供的便利操作数据库了,不过也有不同的操作方式,我们先一个一个的来。

使用mybatis:基于注解的方式

基于注解的方式无需指明任何配置,直接编写相关的注解语句即可,我们只专注自己的Mapper就可以了。

接下来我们测试一下怎么使用基于注解的方式操作数据库。我们新建一个Mapper接口,里面包括了基本的增删查改操作:

mapper/DepartMentMapper.class

package com.zhaoyi.mbweb.mapper;

import com.zhaoyi.mbweb.bean.Department;
import org.apache.ibatis.annotations.*;

@Mapper
public interface DepartmentMapper {

    // insert a derpartment.
    // @Options(useGeneratedKeys = true, keyProperty = \"id\") may you want get insert data generated id.
    @Insert(\"insert into department(id,department_name) values(#{id}, #{departmentName})\")
    int insertDepartment(Department department);

    // delete a department by id.
    @Insert(\"delete from department where id = #{id}\")
    int deleteDepartment(Integer id);

    // query a department by id.
    @Select(\"select * from department where id = #{id}\")
    Department getDepartmentById(Integer id);

    // update a department information.
    @Update(\"update department set department_name=#{departmentName} where id=#{id}\")
    int updateDepartment(Department department);
}

其中:

  • @Mapper 指定这是一个操作数据库的Mapper;
  • 如果你的表是自增类型的,想要获得返回id的信息,可以在插入语句上方加入注解@Options(useGeneratedKeys = true, keyProperty = \"id\"),这样,在插入后mybatis就会自动的将id属性回写到你的插入对象中了;
  • 可以通过#{xxx}语法提取参数中传递的值;

然后,编写一个controller来测试这些操作,为了方便,我们就只测试查询和插入操作即可:

controller/DepartmentController.class

package com.zhaoyi.mbweb.controller;

import com.zhaoyi.mbweb.bean.Department;
import com.zhaoyi.mbweb.mapper.DepartmentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DepartmentController {
    @Autowired
    private DepartmentMapper departmentMapper;

    @GetMapping(\"/department/{id}\")
    public Department getDepartment(@PathVariable(\"id\") Integer id){
        return  departmentMapper.getDepartmentById(id);
    }

    @GetMapping(\"/department\")
    public Department insertDepartment(Department department){
        departmentMapper.insertDepartment(department);
        return department;
    }

}

其中:

  • getDepartment映射/department/{id}的请求,用于处理查询某个id的部门信息,id写在路径参数中;
  • insertDepartment映射/department?xxx=xxx的请求,用于插入get传递的参数中指定的部门信息;

一切完毕,运行项目后,我们分别测试两个操作的结果:

  1. 访问: http://localhost:8086/department/2,我们可以得到以下的输出:
{\"id\":2,\"departmentName\":null}
  1. 访问:http://localhost:8086/department?id=3&name=广州冒险者公会,我们得到以下的输出:
{\"id\":3,\"departmentName\":\"广州冒险者公会\"}

并可以在数据库中看到该条数据。这就是基于注解的方式来使用mybatis操作数据库。

开启驼峰映射规则

细心的朋友应该会发现,查询的部门信息的时候返回的数据的departmentName的值为空。这显然是不对的,我们可以留意到在数据库中我们的命名方式是下划线的department_name,而bean中则是departmentName。这就需要我们开启驼峰映射规则,来提醒mybatis将数据库的下划线字段和bean的驼峰变量关联起来。

如何修改呢?

我们观察mybatis的自动配置类

@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class MybatisAutoConfiguration {
    ...
    
    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setVfs(SpringBootVFS.class);
        if (StringUtils.hasText(this.properties.getConfigLocation())) {
            factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
        }

        org.apache.ibatis.session.Configuration configuration = this.properties.getConfiguration();
        if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
            configuration = new org.apache.ibatis.session.Configuration();
        }

        // 从这里可以知道可以通过配置ConfigurationCustomizer来操作mybatis的配置
        if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
            Iterator var4 = this.configurationCustomizers.iterator();

            while(var4.hasNext()) {
                ConfigurationCustomizer customizer = (ConfigurationCustomizer)var4.next();
                customizer.customize(configuration);
            }
        }

        factory.setConfiguration(configuration);
        if (this.properties.getConfigurationProperties() != null) {
            factory.setConfigurationProperties(this.properties.getConfigurationProperties());
        }

        if (!ObjectUtils.isEmpty(this.interceptors)) {
            factory.setPlugins(this.interceptors);
        }

        if (this.databaseIdProvider != null) {
            factory.setDatabaseIdProvider(this.databaseIdProvider);
        }

        if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
            factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
        }

        if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
            factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
        }

        if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
            factory.setMapperLocations(this.properties.resolveMapperLocations());
        }

        return factory.getObject();
    }
    ...
}

可以发现,我们可以通过增加ConfigurationCustomizer类型的Bean,就可以修改mybatis的配置信息了。添加配置:

config/MyBatisConfig.class

package com.zhaoyi.mbweb.config;


import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class MyBatisConfig {

    @Bean
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer(){
            @Override
            public void customize(Configuration configuration) {
                // 开启驼峰映射规则
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

接下来,我们重启项目,就可以发现,可以正常的获得部门信息了,继续访问刚才的地址http://localhost:8086/department/2,获取id为2的部门信息:

{\"id\":2,\"departmentName\":\"城市冒险者公会\"}

批量扫描Mapper接口

通过前面的介绍,我们需要留意一点,就是编写Mapper的时候要为其添加@Mapper注解,这样才能让mybatis识别这些mapper。但是在实际的开发过程中,Mapper肯定是一个不少的量的,至少,为了简洁考虑,您需要为每个数据表映射一个Mapper,有没有一种一劳永逸的方法呢?

有!

我们只需在MyBaticConfig加上扫描注解或者SpringBoot的启动类上添加@MapperScan(value=\"your mapper packagePath\"),例如,我们可以在上面的mybatis配置类这样写:

config/MybatisConfig.class

// batch scan all mapper class.
@MapperScan(value = \"com.zhaoyi.mbweb.mapper\")
@org.springframework.context.annotation.Configuration
public class MyBatisConfig {

com.zhaoyi.mbweb.mapper 是我的mapper所在的包名,请按您自己的包名进行填写。

使用mybatis:基于配置的方式

更多信息请参考: 官方文档

前面我们使用了基于注解的方式对数据库进行了操作,现在,我们试试另外一种方式,通过配置文件的方式来使用mybatis操作数据库。为了方便,我们接下来的这种方式就来操作user表进行演示即可。

编写Mapper

首先,编写一个user的mapper

mapper/UserMapper.class

package com.zhaoyi.mbweb.mapper;

import com.zhaoyi.mbweb.bean.User;

public interface UserMapper {

    int insertUser(User user);

    int deleteUser(Integer id);

    User getUserById(Integer id);

    int updateUser(User user);
}

和之前的DepartmentMapper不同的是,我们这里并没有添加注解,因为,我们将会把他们写在对应的mybatis SQL映射文件中。

设置应用程序全局配置文件

接下来我们要指定Mybatis配置文件以及Mybatis SQL映射文件的路径,在配置文件中添加如下配置

application.yml

server:
  port: 8086
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://10.21.1.47:3306/joyblack?characterEncoding=utf8&serverTimezone=GMT
    driver-class-name: com.mysql.cj.jdbc.Driver
    initialization-mode: always
    sql-script-encoding: utf-8
    #schema:
    # - classpath:sql/joyblack.sql
mybatis:
  # mybatis配置文件
  config-location: classpath:mybatis/mybatis-config.xml
  # SQL映射文件路径,查看源码他是一个String数组,不过我们直接配置\"*\"通配符即可,代表所有的xml文件
  mapper-locations: classpath:mybatis/mapper/*.xml

配置Mybatis配置文件

在资源文件夹下创建mybatis文件夹,并放入mybatis-config.xml(和全局配置指定的路径一致)配置文件

resources/mybatis/mybatis-config.xml

<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<!DOCTYPE configuration
        PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\"
        \"http://mybatis.org/dtd/mybatis-3-config.dtd\">
<configuration>
    <settings>
       <setting name=\"mapUnderscoreToCamelCase\" value=\"true\" />
    </settings>
</configuration>

里面配置一些相关配置,例如数据库连接信息等,但这些我们已经在数据源配置了,这里就无需配置。

如果我们没有在mybatis的主配置文件中配置mapUnderscoreToCamelCase,这时候我们去查询部门相关的信息,发现名字又为空了。因为当使用配置文件之后,我们的自定义配置中设置的驼峰式映射逻辑已经被配置文件的默认配置覆盖掉了。因此,我们需要在配置文件中指定驼峰时映射规则:

resources/mybatis/mybatis-config.xml

<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<!DOCTYPE configuration
        PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\"
        \"http://mybatis.org/dtd/mybatis-3-config.dtd\">
<configuration>
    <settings>
       <setting name=\"mapUnderscoreToCamelCase\" value=\"true\" />
    </settings>
</configuration>

可以发现,配置项mapUnderscoreToCamelCase和我们使用配置文件的属性名是一模一样的。

从这里可以看出,两种方式混用也是可以的,但是问题很明显,配置会冲突。所以大家在开发的时候最好还是选择其中一种方式,从始至终进行,避免管理上的复杂以及逻辑的混乱。

配置Mybatis SQL映射文件

对应配置文件创建一个mapper文件夹,用于放我们的SQL映射文件,在这里我们创建一个UserMapper.xml即可.

resources/mybatis/mapper/UserMapper.xml

<?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.zhaoyi.mbweb.mapper.UserMapper\">
    <!--     int insertUser(User user);

    int deleteUser(Integer id);

    User getUserById(Integer id);

    int updateUser(User user);-->
    @font-face {
				font-family: "autolinktags";
				src: url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.woff2") format("woff2"),
				url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.woff") format("woff"),
				url("https://www.seowoai.com/zb_users/plugin/AutoLinkTags/style/fonts/iconfont.ttf") format("truetype");
				font-weight:normal;
				font-style:normal;
			}.tagslink::after { content:"\e613"; margin:2px 0 0 0px; font-size:12px; font-family:"autolinktags"; display:inline-block; vertical-align:top; }															
版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表