天天看点

Java实战干货|Spring Boot整合MyBatis框架快速实现数据操作

作者:java易

一. Spring Boot数据访问概述

Spring Data是Spring提供的一个用于简化数据库访问、支持云服务的开源框架。它是一个伞形项目,包含了大量关系型数据库及非关系型数据库的数据访问解决方案,其设计目的是使我们可以快速且简单地使用各种数据访问技术。Spring Boot默认采用整合Spring Data的方式统一处理数据访问层,通过添加大量自动配置,引入各种数据访问模板xxxTemplate以及统一的Repository接口,从而达到简化数据访问层的操作。

Spring Data提供了多种类型数据库支持,Spring Boot对Spring Data支持的数据库进行了整合管理,提供了各种依赖启动器。通过一张表罗列Spring Boot提供的常见数据库依赖启动器。

名称 描述
mybatis-spring-boot-starter MyBatis启动器
mybatis-plus-boot-starter MyBatis-Plus启动器
spring-boot-starter-data-jpa Spring Data JPA与Hibernate的启动器
spring- boot starter-data-redis Redis键值数据存储与Spring Data Redis和Jedis客户端的启动器
spring-boot-starter-data-neo4j Neo4j图数据库和Spring Data Neo4j的启动器
spring-boot-starter-data-mongodb MongoDB和Spring Data MongoDB的启动器

二. Spring Boot整合MyBatis实现

MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解配置和映射原生信息,并将接口和Java的POJO(Plain Old Java Objects,普通Java对象)映射成数据库中的记录。

MyBatis作为操作数据库的流行框架,Spring Boot没有提供MyBatis场景依赖,但是MyBatis开发团队自己适配了Spring Boot,提供了mybatis-spring-starter依赖启动器实现数据访问操作。进一步简化了MyBatis对数据的操作。

1.基础环境搭建

实现Spring Boot与数据访问层框架(例如MyBatis)的整合非常简单,主要是引入对应的依赖启动器,并进行数据库相关参数设置即可。

1.1 数据准备

在MySQL中创建一个名称为springbootdata的数据库。

# 创建数据库
CREATE DATABASE springbootdata character SET utf8;           

在该数据库中创建两个表t_article和t_comment。

# 选择使用数据库
USE springbootdata;

# 创建文章表t_article并插入相关数据
DROP TABLE IF EXISTS t_article;

CREATE TABLE t_article (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '文章id',
  title varchar(50) NOT NULL COMMENT '文章标题',
  content longtext COMMENT '文章具体内容',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t_article VALUES ('1', 'SSM框架基础教程', '从入门到精通...');
INSERT INTO t_article VALUES ('2', 'SPringBoot框架基础教程', '从入门到精通...');

# 创建评论表t_comment并插入相关数据
DROP TABLE IF EXISTS t_comment;

CREATE TABLE t_comment (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '评论id',
  article_id int(11) NOT NULL COMMENT '关联的文章id',
  content longtext COMMENT '评论内容',
  author varchar(200) DEFAULT        NULL COMMENT '评论用户用户名',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO t_comment VALUES ('1', '1', '内容很详细', '明明');
INSERT INTO t_comment VALUES ('2', '1', '已三连', '红红');
INSERT INTO t_comment VALUES ('3', '1', '很不错', '小王');
INSERT INTO t_comment VALUES ('4', '1', '赞一个', '东东');
INSERT INTO t_comment VALUES ('5', '2', '内容全面', '方方');           

1.2 搭建项目

创建一个项目名称为chapter03的Spring Initializr类型的项目。在Dependencies依赖中选择SQL模块中的MySQL和MyBatis依赖。

然后编写数据库表对应的实体类。在com.cy.domain包下,并在该包中编写与数据库表t_article和t_comment对应的实体类Comment和Article类。

(1) 在com.cy.domain包下创建Comment实体类。

package com.cy.domain;
/** 评论实体类 */
public class Comment {
    private Integer id;
    private Integer articleId;
    private String content;
    private String author;
    // Generate: Getter and Setter、toString()
}               

(2) 在com.cy.domain包下创建Article实体类。

package com.cy.domain;
import java.util.List;
/** 文章实体类 */
public class Article {
    private Integer id;
    private String title;
    private String content;
    private List<Comment> commentList;
    // Generate: Getter and Setter、toString()
}             

1.3 编写配置文件

首先在application.properties配置文件中编写对应的MySQL数据库连接配置。

# MySQL数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456           

然后对数据源类型选择配置。Spring Boot 1.x版本默认使用的是tomcat.jdbc数据源,Sprng Boot 2.x版本默认使用的是Hikari数据源。如果使用其他数据源,还需要进行额外配置。这里选择使用阿里巴巴的Druid数据源。在pom.xml文件中添加Druid数据源的依赖启动器。

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.17</version>
</dependency>           

引入的druid-spring-boot-starter依赖,是阿里巴巴为了迎合Spring Boot项目而适配的Druid数据源启动器,当在pom.xml文件中引入该启动器后,不需要再进行其他额外配置,Spring Boot项目会自动识别配置Druid数据源。

上述配置的Druid数据源启动器内部已经初始化了一些运行参数(例如initialSize、maxActive等),如果开发过程中需要修改第三方Druid的运行参数,则必须在全局配置文件中修改。

# MySQL数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
# 添加并配置第三方数据源Druid
# 数据源类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化连接数
spring.datasource.initialSize=20
# 最小空闲数
spring.datasource.minIdle=10
# 最大连接数
spring.datasource.maxActive=100           

在application.properties中添加上述配置后,会发现配置的initialSize、minIdle和maxActive属性底色为黄色(IDEA开发工具中的显示色)。这是因为在Spring Boot提供的数据源自动配置类org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中,没有与这些参数对应的默认属性,所以这些设置的属性值无法识别和生效。因此需要编写一个自定义配置类,将配置文件中的属性注入到Druid数据源属性中。

接着我们要在com.cy.config包下创建一个DataSourceConfig自定义配置类,对Druid数据源属性值进行注入。

package com.cy.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDruid() {
        return new DruidDataSource();
    }
}           

2.使用注解的方式整合MyBatis

创建Mapper接口文件。在com.cy.mapper包下创建一个用于对数据库表t_comment数据操作的接口CommentMapper。

package com.cy.mapper;
import com.cy.domain.Comment;
import org.apache.ibatis.annotations.*;
@Mapper
public interface CommentMapper {
    @Select("SELECT * FROM t_comment WHERE id=#{id}")
    Comment findById(Integer id);
    @Insert("INSERT INTO t_comment(article_id,content,author) " +
            "values (#{articleId},#{content},#{author})")
    Integer insertComment(Comment comment);
    @Update("UPDATE t_comment SET content=#{content} WHERE id=#{id}")
    Integer updateComment(Comment comment);
    @Delete("DELETE FROM t_comment WHERE id=#{id}")
    Integer deleteComment(Integer id);
}           

说明:在对应的接口类上添加@Mapper注解,如果编写的Mapper接口过多时,需要重复为每一个接口文件添加@Mapper注解,为了避免这种麻烦,可以直接在Spring Boot项目启动类上添加@MapperScan("xxx")注解,参数必须指定需要扫描的具体包名。

然后在com.cy测试包下创建MyBatisTests类,并在MyBatisTests类中引入CommentMapper接口,并对接口中方法进行测试。

package com.cy;
import com.cy.domain.Comment;
import com.cy.mapper.CommentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MyBatisTests {
    @Autowired
    private CommentMapper commentMapper;

    @Test
    public void findById() {
        Comment comment = commentMapper.findById(1);
        // Comment{id=1, articleId=null, content='内容很详细', author='明明'}
        System.out.println(comment);
    }
    @Test
    public void insertComment() {
        Comment comment = new Comment();
        comment.setArticleId(2);
        comment.setContent("文章写的很棒");
        comment.setAuthor("张三");
        commentMapper.insertComment(comment);
    }
    @Test
    public void updateComment() {
        Comment comment = new Comment();
        comment.setId(6);
        comment.setContent("赞赞赞");
        commentMapper.updateComment(comment);
    }
    @Test
    public void deleteComment() {
        commentMapper.deleteComment(6);
    }
}           

我们会发现控制台中查询的Comment的articleId属性值为null,没有映射成功。这是因为编写的实体类Comment中使用了驼峰命名方式将t_comment表中的article_id字段设计成了articleId属性,所以无法正确映射查询结果。为了解决上述由于驼峰命名方式造成的表字段值无法正确映射到类属性的情况,可以在Spring Boot全局配置文件application.properties中添加开启驼峰命名匹配映射配置。

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

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

Spring Boot与MyBatis整合使用时,不仅支持注解方式,还支持XML配置文件的方式。在com.cy.mapper包中创建一个操作数据表t_article的接口ArticleMapper。

package com.cy.mapper;
import com.cy.domain.Article;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ArticleMapper {
    Article findArticleById(Integer id);
    Integer updateArticle(Article article);
}           

创建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.cy.mapper.ArticleMapper">
    <resultMap id="articleWithComment" type="Article">
        <id property="id" column="id" />
        <result property="title" column="title" />
        <result property="content" column="content" />
        <collection property="commentList" ofType="Comment">
            <id property="id" column="id" />
            <result property="articleId" column="article_id" />
            <result property="content" column="content" />
            <result property="author" column="author" />
        </collection>
    </resultMap>
    <select id="findArticleById" resultMap="articleWithComment">
        SELECT a.*, c.*
        FROM t_article a, t_comment c
        WHERE a.id = c.article_id AND a.id = #{id}
    </select>
    <update id="updateArticle" parameterType="Article">
        UPDATE t_article
        <set>
            <if test="title !=null and title !=''">
                title=#{title},
            </if>
            <if test="content !=null and content !=''">
                content=#{content}
            </if>
        </set>
        WHERE id=#{id}
    </update>
</mapper>           

配置XML映射文件路径。在全局配置文件application.properties中添加MyBatis映射文件路径的配置,同时需要添加实体类别名映射路径。

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

最后编写单元测试进行接口方法测试,在测试类MyBatisTests中对接口方法进行测试。

@Autowired
private ArticleMapper articleMapper;
@Test
public void findArticleById() {
    Article article = articleMapper.findArticleById(1);
    System.out.println(article);
}
@Test
public void updateArticle() {
    Article article = new Article();
    article.setId(1);
    article.setTitle("SSM高级开发");
    article.setContent("高级进阶内容");
    Integer rows = articleMapper.updateArticle(article);
    System.out.println(rows);
}           

继续阅读