首页 > 技术文章 > SpringBoot数据访问(一) SpringBoot整合Mybatis

blayn 2021-06-17 08:51 原文

前言

SpringData是Spring提供的一个用于简化数据库访问、支持云服务的开源框架。它是一个伞形项目,包含了大量关系型数据库及非关系型数据库的数据访问解决方案,其设计目的是为了使我们可以快速且简单地使用各种数据访问技术。

SpringBoot默认采用整合SpringData的方式统一处理数据访问层,通过添加大量自动配置,引入各种数据访问模板xxxTemplate以及统一的Repository接口,从而达到简化数据访问层的操作。

SpringData提供了多种类型数据库支持,对支持的数据库进行了整合,提供了各种依赖启动器,常见数据库依赖启动器如下表所示:

 

除此之外,还有一些框架技术,SpringData项目并没有进行统一管理,SpringBoot官方也没有提供对应的依赖启动器,但是为了迎合市场开发需求,这些框架技术的开发团队自己适配了对应的依赖启动器,例如,mybatis-spring-boot-starter支持MyBatis的使用。

SpringBoot整合MyBatis

MyBatis是一款优秀的持久层框架,虽然SpringBoot官方并没有对Mybatis进行整合,但是Mybatis技术团队自行适配了对应的启动器,进一步简化了使用Mybatis进行数据的操作。

SpringBoot整合MyBatis的步骤非常简单,只需要引入相关的依赖启动器,再进行数据库相关设置即可。

基础环境搭建

1、数据准备

在MySQL中,执行以下sql脚本:

# 创建数据库
CREATE DATABASE springbootdata;
# 选择使用数据库
USE springbootdata;
# 创建表t_article并插入相关数据
DROP TABLE IF EXISTS t_article;
CREATE TABLE t_article (
 id INT(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
 title VARCHAR(200) DEFAULT NULL COMMENT '文章标题',
 content LONGTEXT COMMENT '文章内容',
 PRIMARY KEY (id)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO t_article VALUES ('1', 'SpringBoot基础入门', '从入门到放弃...');
INSERT INTO t_article VALUES ('2', 'SpringCloud基础入门', '从入门到转行...');

# 创建表t_comment并插入相关数据
DROP TABLE IF EXISTS t_comment;
CREATE TABLE t_comment (
 id INT(20) NOT NULL AUTO_INCREMENT COMMENT '评论id',
 content LONGTEXT COMMENT '评论内容',
 author VARCHAR(200) DEFAULT NULL COMMENT '评论作者',
 a_id INT(20) DEFAULT NULL COMMENT '关联的文章id',
 PRIMARY KEY (id)
 ) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO t_comment VALUES ('1', '很好、很详细', 'luccy', '1');
INSERT INTO t_comment VALUES ('2', '赞一个', 'tom', '1');
INSERT INTO t_comment VALUES ('3', '很全面', 'eric', '1');
INSERT INTO t_comment VALUES ('4', '很好、很全面', '张三', '1');
INSERT INTO t_comment VALUES ('5', '很不错', '李四' ,'2');

以上脚本创建了一个名为springbootdata的数据库,然后创建了两张数据表:t_article和t_comment并向这两张表插入相关数据,其中评论表t_comment的a_id与文章表t_article的主键id相关联。

2、创建项目,引入相应的启动器

引入这两个依赖器创建项目,在项目pom.xml文件会出现以下依赖:

3、编写与数据库t_article和t_comment和对应的实体类Comment和Article

package com.hardy.springbootdata.entity;

/**
 * @Author: HardyYao
 * @Date: 2021/6/12
 */
public class Article {

    private Integer id;

    private String title;

    private String content;

    public Integer getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "Article{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

 

package com.hardy.springbootdata.entity;

/**
 * @Author: HardyYao
 * @Date: 2021/6/12
 */
public class Comment {

    private Integer id;

    private String content;

    private String author;

    private Integer aId;

    public Integer getId() {
        return id;
    }

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

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Integer getaId() {
        return aId;
    }

    public void setaId(Integer aId) {
        this.aId = aId;
    }

    @Override
    public String toString() {
        return "Comment{" +
                "id=" + id +
                ", content='" + content + '\'' +
                ", author='" + author + '\'' +
                ", aId=" + aId +
                '}';
    }
}

4、编写配置文件

# MySQL数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

使用注解的方式整合Mybatis

(1)编写针对t_comment数据表的mapper数据操作接口

package com.hardy.springbootdata.mapper;

import com.hardy.springbootdata.entity.Comment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

/**
 * @Author: HardyYao
 * @Date: 2021/6/12
 */
@Mapper
public interface CommentMapper {
    
    @Select("SELECT * FROM t_comment WHERE id =#{id}")
    Comment findById(Integer id);
    
}

针对该接口类的讲解:@Mapper注解表示该类是一个MyBatis接口文件,并保证能够被SpringBoot自动扫描到Spring容器中。

这里有个问题,如果编写的Mapper接口过多时,那么就需要在很多个接口类上面添加@Mapper注解,这样会比较耗时间。为了解决这个问题,可以直接在SpringBoot项目启动类上添加@MapperScan("xxx")注解(如 @MapperScan("com.hardy.springbootdata.mapper")),这样就不需要再逐个添加@Mapper注解。(@MapperScan注解作用和@Mapper注解相似,但它必须指定需要扫描的具体包名)。

(2)编写测试方法

package com.hardy.springbootdata;

import com.hardy.springbootdata.entity.Comment;
import com.hardy.springbootdata.mapper.CommentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootdataApplicationTests {

    @Autowired
    private CommentMapper commentMapper;

    @Test
    void contextLoads() {
        Comment comment = commentMapper.findById(1);
        System.out.println(comment);
    }

}

控制台打印结果:

由上图可知,查询到的Comment的aId值为null,没有映射成功。这是因为编写的实体类Comment中使用了驼峰命名方式将t_comment表中的a_id字段设计成了aId属性,所以无法正确映射查询结果。

为了解决这个问题,可以在SpringBoot全局配置文件application.properties中添加开启驼峰命名匹配映射配置,示例代码如下:

# 开启驼峰命名匹配映射
mybatis.configuration.map-underscore-to-camel-case=true

再次运行测试方法,控制台打印结果:

可以看到,这次aId映射成功了。

使用配置文件的方式整合MyBatis

(1)编写针对t_article数据表的mapper数据操作接口

package com.hardy.springbootdata.mapper;

import com.hardy.springbootdata.entity.Article;
import org.apache.ibatis.annotations.Mapper;

/**
 * @Author: HardyYao
 * @Date: 2021/6/12
 */
@Mapper
public interface ArticleMapper {

    Article selectArticle(Integer id);

}

(2)创建XML映射文件

在resources目录下创建一个统一管理映射文件的mapper包,并在该包下编写与ArticleMapper接口相应的映射文件ArticleMapper.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.hardy.springbootdata.mapper.ArticleMapper">
    
    <select id="selectArticle" resultType="com.hardy.springbootdata.entity.Article">
        select * from t_article where id = #{id, jdbcType=BIGINT}
    </select>
    
</mapper>

(3)配置XML映射文件路径。前面我们编写的XML文件,SpringBoot是无法自己感知到的,即SpringBoot无法扫描到我们编写的XML配置文件,所以我们还需要在全局配置文件application.properties中添加MyBatis映射文件路径的配置,同时需要添加实体类别名映射路径,示例代码如下:

# 配置Mybatis的XML配置文件路径
mybatis.mapper-locations=classpath:mapper/*.xml
# 配置XML映射文件中指定的实体类别名路径
mybatis.type-aliases-package=com.hardy.springbootdata.entity

(4)编写单元测试进行接口方法测试

@Autowired
private ArticleMapper articleMapper;
    
@Test
public void selectArticle() {
    Article article = articleMapper.selectArticle(1);
    System.out.println(article);
}

打印结果:

推荐阅读