目录:
- 一、Spring Boot”数据访问概述“
- 二、Spring Boot”整合MyBatis”
- 1. 基础环境搭建 (引入对应的“依赖启动器” + 配置数据库的“相关参数”)
- ① 数据准备 (导入Sql文件)
- ② 创建项目,引入相应的启动器,编写数据库对应的“实体类”
- ③额外添加pom.xml文件依赖
- ④ 编写application.properties 配置文件
- ⑤ 编写自定义的关于“DruidDataSource“ 的 配置类”
- 2. 使用“注解”的方式整合MyBatis ( 使用 “注解” 来“直接”操作数据库)
- 3. 使用“配置文件”的方式整合MyBatis ( 使用 “XxxMapper.java文件 + XxxMapper.xml文件” 来 操作数据库)
作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!
该文章参考学习教材为:
《Spring Boot企业级开发教程》 黑马程序员 / 编著
文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!(侵权可联系我,进行删除,如果雷同,纯属巧合)
一、Spring Boot”数据访问概述“
Spring Data 是 Spring 提供的一个用 于简化数据库访问、支持云服务的开源框架。它是一个 伞形项目,包含了 大量关系型数据库 及 非关系型数据库 的 数据访问解决方案,其设计目的是使我们可以快速且简单地使用各种数据访问技术。
Spring Boot默认采用整合 Spring Data 的方式统一处理数据访问层,通过添加大量自动配置,引入各种数据访问模板 xxxTemplate 以及统一的 Repository 接口,从而达到简化数据访问层的操作。
Spring Data 提供了 多种类型数据库支持,Spring Boot对 Spring Data支持的数据库进行了 整合管理 ,提供了 各种依赖启动器。
常见的 数据库依赖启动器,如下表所示 :
名称 描述 spring-boot-starter-data-jpa Spring Data JPA 与 Hibernate 的启动器 spring-boot-starter-data-mongodb MongoDB 和 Spring Data MongoDB 的启动器 spring-boot-starter-data-neo4j Neo4j 图数据库 和 Spring Data Neo4j 的启动器 spring-boot-starter-data-redis Redis键值数据存储 与 Spring Data Redis 和 Jedis客户端 的启动器 需要说明的是,MyBatis作为操作数据库的流行框架,Spring Boot没有提供MyBatis 场景
依赖,但是 MyBatis开发团队自己适配了Spring Boot,提供了 mybatis-spring-boot-starter
依赖启动器实现数据访问操作。
二、Spring Boot”整合MyBatis”
- MyBatis 是一款优秀的持久层框架,它支持 定制化SQL、存储过程以及高级映射,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
- MyBatis可以使用简单的 XML 或 注解 配置和映射原生信息,并将 接口 和Java的 POJOs ( Plain Old Java Objects,普通Java对象) 映射成数据库中的记录。Spring Boot 官方虽然没有对MyBatis进行整合,但是MyBatis 团队自行适配了对应的启动器,进一步简化了MyBatis 对数据的操作。
1. 基础环境搭建 (引入对应的“依赖启动器” + 配置数据库的“相关参数”)
因为SpringBoot 框架开发很便利,所以实现 Spring Boot 与 数据访问层框架( 例如MyBatis ) 的整合非常简单,主要是 引入对应的依赖启动器,并进行 数据库相关参数设置 即可。
① 数据准备 (导入Sql文件)
先创建了一个 数据库springbootdata,然后创建了两个表 t_article和t_comment ,并向表中插入数据。
其中评论表t_comment 的a_id 与文章表t_article 的主键id 相关联 ( t_article的主键作为t_comment表的 “外键”)。springbootdata.sql
② 创建项目,引入相应的启动器,编写数据库对应的“实体类”
使用 Spring Initializr 的方式 创建 Spring Boot 项目。在Dependencies依赖中选择 SQL 模块中的 MySQL 和 MyBatis依赖,并根据后续提示完成项目创建。
编写 数据库 对应的 “实体类” :
Article.java :
package com.myh.chapter_04.domain; import java.util.List; public class Article { private Integer id; private String title; private String content; private List<Comment> commentList; 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; } public List<Comment> getCommentList() { return commentList; } public void setCommentList(List<Comment> commentList) { this.commentList = commentList; } @Override public String toString() { return "Article{" + "id=" + id + ", title='" + title + '\'' + ", content='" + content + '\'' + ", commentList=" + commentList + '}'; } }
Comment.java :
package com.myh.chapter_04.domain; public class Comment { private Integer id; private String content; private String atuthor; private Integer aId; //Article表的主键作为Comment表的"外键" 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 getAtuthor() { return atuthor; } public void setAtuthor(String atuthor) { this.atuthor = atuthor; } public Integer getaId() { return aId; } public void setaId(Integer aId) { this.aId = aId; } @Override public String toString() { return "Comment{" + "id=" + id + ", content='" + content + '\'' + ", atuthor='" + atuthor + '\'' + ", aId=" + aId + '}'; } }
③额外添加pom.xml文件依赖
额外添加的 pom.xml文件依赖 :
<!-- druid数据库连接池的"依赖启动器" --> <!-- 该依赖中的version不能省略,因为其是阿里巴巴为了迎合Springboot而有,不是Springboot自己制作的 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency>
上述引入的依赖druid-spring-boot-starter,同样是 阿里巴巴为了迎合Spring Boot 项目 而适配的 Druid 数据源启动器,当在pom.xml文件中引入该启动器后,不需要再进行其他额外配置,Spring Boot项目会自动识别配置Druid 数据源。需要说明的是,上述配置的Druid 数据源启动器内部已经初始化了一些运行参数( 例如 initialSize、minIdle、maxActive 等),如果开发过程中需要修改第三方Druid的运行参数,则必须在全局配置文件中修改。
④ 编写application.properties 配置文件
- 在 application.properties配置文件 中 进行数据库连接配置。打开全局配置文件 application.properties,在配置文件中编写对应的 MySQL数据库连接配置,内容如下 :
application.properties :
spring.application.name=chapter_06 #配置数据库信息 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent=true spring.datasource.username=root spring.datasource.password=root #添加并配置第三方数据源Druid(数据库连接池) spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #初始化时创建的连接数。当应用程序启动时,连接池会立即创建这么多连接。 spring.datasource.initialSize=20 #连接池中最小的空闲连接数。连接池会维护至少这么多的空闲连接,当空闲连接数低于这个数值时,连接池会创建新的连接。 spring.datasource.minIdle=10 #连接池中最大的活动连接数。这表示在任何时候,连接池中的活动(即被使用的)连接数不会超过这个数值。如果所有连接都在使用中,并且达到这个上限,那么新的数据库连接请求将被阻塞或拒绝,直到有连接可用。 spring.datasource.maxActive=100
配置文件中修改了 Druid数据源的类型、初始化连接数、最小空闲连接数、最大连接数,如果有其他需求,还可以参考 Druid 属性设置更多参数。
- 在上面的 application.properties配置文件 中添加 上述配置 后,会发现initialSize、minIdle 和 maxActive 底纹为黄色 (IDEA工具中的显示色) , 这是因为在Spring Boot 提供的 数据源自动配置类 :org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 中,没有 与这些 参数对应的默认属性,所以 这些设置的属性值 ”无法识别“和生效 ,但这几个属性是 有用的,为 “自定义配置类” 服务的。然后接下来的操作是就是 : 编写一个自定义配置类,将配置文件中的属性 注入到DruidDataSource类的属性中
ps:
(为什么要 创建 一个 返回值 为 :DruidDataSource的 自定义 “配置类” 呢 ? 因为要用到 application.properties 中 添加的“配置参数” ,通过 @ConfigurationProperties( )注解 来将application.properties中的相关参数注入到DruidDataSource类中,通过这些“配置参数”来 修改Druid中的默认配置。)
⑤ 编写自定义的关于“DruidDataSource“ 的 配置类”
编写 自定义的“配置类” : (该 配置的作用 :创建一个 DruidDataSource对象,然后将 application.properties 中关于Druid中的参数注入到 DruidDataSource对象)
package com.myh.chapter_04.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 { //关于DruidDataSource的“配置类” @ConfigurationProperties("spring.datasource") //将配置文件中的spring.datasource开头的“属性值”注入到DruidDataSource对象中的“属性”中 @Bean //将该方法的返回值“对象”交给IOC容器管理 public DataSource getDruid() { return new DruidDataSource(); //返回值为一个DruidDataSource对象 } }
在上面的代码中,通过 @Configuration注解标识了一个自定义配置类DataSourceConfig,在该配置类中通过 @Bean注解注入了一个DataSource实例对象,@ConfigurationProperties(prefix =“spring.datasource”) 注解的作用是将全局配置文件中以spring.datasource开头的属性值注入到 getDruid( )方法返回的DataSource类对象属性中,这样就可以完成第三方数据源参数值的注入。
2. 使用“注解”的方式整合MyBatis ( 使用 “注解” 来“直接”操作数据库)
相比 Spring 与 Mybatis的整合,Spring Boot与MyBatis的整合会使项目开发更加简便,同时还支持 XML 和 注解 两种配置方式。
通过 “注解” 的方式 整合Mybatis 的例子如 :
CommentMapper.java (接口) :
package com.myh.chapter_05.mapper; import com.myh.chapter_05.domain.Comment; import org.apache.ibatis.annotations.*; @Mapper //将该接口加入到IOC容器中 public interface CommentMapper { @Select("select * from t_comment where id = #{id}") public Comment findById(Integer id); @Insert("insert into t_comment(content,author,a_id) " + "values(#{content},#{author},#{aId})") public int insertComment(Comment comment); @Update("update t_comment et content = #{content} where id = #{id}") public int updateComment(Comment comment); @Delete("delete from t_comment where id = #{id}") public int deleteComment(Integer id); }
上面的代码中,@Mapper( )注解表示该类是一个MyBatis接口文件,并保证能够被Spring Boot自动扫描到 Spring 容器中;在该接口内部,分别通过 @Select( )、@lnsert( )、@Update( )、@Delete( )
注解配合 SQL 语句完成了对数据库表t_comment表数据的 增删改查 操作。
”增删改查“注解 描述 @Select( )、@Insert( )、@Update( )、@Delete( ) 这四个注解用于 映射“sql语句” 到 接口方法上 ,这样调用接口方法就能操作数据库。
注意点 :
上面的CommentMapper.java 的代码中了添加 @Mapper 注解,如果编写的Mapper接口过多时,需要重复为每一个接口文件添加 @Mapper 注解。为了==避免这种麻烦,可以直接在Spring Boot项目启动类上添加@MapperScan(“xxx”)注解,不需要再逐个添加 @Mapper 注解。@MapperScan(“xxx”)注解的作用和 @Mapper注解类似,但是它必须指定需要扫描的具体包==名,例如 @MapperScan(“com.itheima.mapper”)。
注解 描述 @Mapper注解 @Mapper注解通常只用在接口上,用于将接口加入到IOC容器中。 @MapperScan(“需要扫描的包名”)注解 用于将指定包下的接口 全都加入到IOC容器中。在 SpringBoot 中该注解用在 “项目的启动类”上。 @MapperScan(" ")注解 例子如:
@SpringBootApplication @MapperScan("com.myh.chapter_05.mapper") //将该包下的所有接口都加入到IOC容器中 public class Chapter05Application { public static void main(String[] args) { SpringApplication.run(Chapter05Application.class, args); } }
application.properties :
spring.application.name=chapter_06 #配置数据库信息 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent=true spring.datasource.username=root spring.datasource.password=root #添加并配置第三方数据源Druid(数据库连接池) spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #初始化时创建的连接数。当应用程序启动时,连接池会立即创建这么多连接。 spring.datasource.initialSize=20 #连接池中最小的空闲连接数。连接池会维护至少这么多的空闲连接,当空闲连接数低于这个数值时,连接池会创建新的连接。 spring.datasource.minIdle=10 #连接池中最大的活动连接数。这表示在任何时候,连接池中的活动(即被使用的)连接数不会超过这个数值。如果所有连接都在使用中,并且达到这个上限,那么新的数据库连接请求将被阻塞或拒绝,直到有连接可用。 spring.datasource.maxActive=100
pom.xml :
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.myh</groupId> <artifactId>chapter_06</artifactId> <version>0.0.1-SNAPSHOT</version> <name>chapter_06</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies> <!-- <build>--> <!-- <plugins>--> <!-- <plugin>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-maven-plugin</artifactId>--> <!-- </plugin>--> <!-- </plugins>--> <!-- </build>--> </project>
Chapter06ApplicationTests.java : (单元测试类)
package com.myh.chapter_06; import com.myh.chapter_06.domain.Comment; import com.myh.chapter_06.mapper.CommentMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Chapter06ApplicationTests { @Autowired private CommentMapper commentMapper; @Test void contextLoads() { Comment comment = commentMapper.findById(1); System.out.println(comment); } }
3. 使用“配置文件”的方式整合MyBatis ( 使用 “XxxMapper.java文件 + XxxMapper.xml文件” 来 操作数据库)
Spring Boot 与MyBatis整合使用时,不仅支持注解方式,还支持XML配置文件的方式 (通过 XxxMapper.java+ XxxMapper.xml的方式来操作数据库 )。
例子如下 :
Article.java :
package com.myh.chapter_06.domain; import java.util.List; public class Article { private Integer id; private String title; //标题 private String content; //文章内容 private List<Comment> commentList; //评论 --要用到“关联映射”的知识点 (为一对多的关系) 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; } public List<Comment> getCommentList() { return commentList; } public void setCommentList(List<Comment> commentList) { this.commentList = commentList; } @Override public String toString() { return "Article{" + "id=" + id + ", title='" + title + '\'' + ", content='" + content + '\'' + ", commentList=" + commentList + '}'; } }
Comment.java :
package com.myh.chapter_06.domain; 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 + '}'; } }
ArticleMapper.java :
package com.myh.chapter_06.mapper; import com.myh.chapter_06.domain.Article; import org.apache.ibatis.annotations.Mapper; @Mapper //将该接口加入到IOC容器中 public interface ArticleMapper { //通过XxxMapper.java 和 XxxMapper.xml配置文件的方式来操作数据库 public Article selectArticle(Integer id); public int updateArticle(Article article); }
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"> <!-- namespace的命名空间 --> <!-- 我们在项目中编写了配置文件,springboot并不知晓,要在全局配置文件中添加Mybatis映射文件的位置--> <mapper namespace="com.myh.chapter_06.mapper.ArticleMapper"> <!-- 查询文章详细信息(包括评论信息) --> <select id="selectArticle" resultMap="articleWithComment"> select a.*,c.id c_id,c.content c_content,c.author from t_article a ,t_comment c where a.id = c.a_id and a.id = #{id} </select> <!-- resultMap进行“关联映射”,进行数据的注入和同时避免字段名和属性名不一致的问题 --> <!-- 因为在全局配置文件中用了该配置 : mybatis.type-aliases-package=com.myh.chapter_06.domain ,则下面写“小写字母开头的类名”即可,不用写全限定类名 --> <resultMap id="articleWithComment" type="article"> <id property="id" column="id"/> <result property="title" column="title"/> <result property="content" column="content"/> <!-- collection : 嵌套结果的方式 --> <collection property="commentList" ofType="comment"> <id property="id" column="c_id"/> <result property="content" column="c_content"/> <result property="author" column="author"/> <result property="aId" column="a_id"/> </collection> </resultMap> <!-- 根据文章id更新文章信息 --> <!-- 用了动态sql的知识点,有值才设置,没则不用设 --> <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>
上面的配置文件中,<mapper>标签的namespace属性值对应的是ArticleMapper.java接口文件的全路径名称,在映射文件中根据ArticleMapper接口文件中的方法,编写两个对应的SQL语句; 同时配置数据类型映射时,没有使用类的全路径名称,而是使用了类的别名(例如,没有使用com.itheima.domain.Article (而是使用了article ) ––因为在 application.properties 中配置了 mybatis.type-aliases-package=com.myh.chapter_06.domain。
注意点 :
我们在项目中编写的XML 映射文件,Spring Boot并无从知晓,所以无法扫描到该自定义编写的XML配置文件,还必须在全局配置文件application.properties
中添加 MyBatis 映射文件路径的配置 ,同时需要添加实体类别名映射路径。(具体代码在application.properties中 )
Chapter06ApplicationTests.java ( 测试类 ) :
package com.myh.chapter_06; import com.myh.chapter_06.domain.Article; import com.myh.chapter_06.domain.Comment; import com.myh.chapter_06.mapper.ArticleMapper; import com.myh.chapter_06.mapper.CommentMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Chapter06ApplicationTests { @Autowired private ArticleMapper articleMapper; @Test public void selectArticle() { Article article = articleMapper.selectArticle(1); System.out.println(article); } }
测试方法运行结果 :
从上图可以看出,selectArticle( )方法执行成功,查询出了文章id 为1的文章详情,并关联查询出了对应的评论信息,这说明使用 配置文件的方式整合MyBatis 成功。对于Spring Boot 支持与MyBatis整合的两种方式而言,使用 注解的方式 比较 适合简单的增删改查操作;而使用 配置文件的方式 稍微麻烦,但对于 复杂的数据操作却显得比较实用。实际开发中,使用Spring Boot整合MyBatis进行项目开发时,通常会 混合使用两种整合方式。