SpringBoot数据访问3系列
3.1 SpringBoot整合MyBatis3.2 SpringBoot整合JPA
3.3 SpringBoot整合Redis
SpringBoot整合MyBatis
概括
本文包含:Spring boot整合MyBatis的两种方式
① 不管是哪种方式都需要先创建数据库,创建表,在配置文件中进行数据库的连接和数据源配置,编写两个实体类(两个表对应的)
② 使用注解方式时,不需要编写xml映射文件,在Mapper接口中就完成了定义方法+对数据库进行操作
③ 使用配置文件时,需要编写Mapper接口,xml配置文件,以及在全局配置文件中指定xml文件位置
一、步骤截图
1. 基础环境搭建
1.1 数据库+表+数据
①创建一个数据库springbootdata,
②然后创建两个表t_article和t_comment,
③并向表中插入数据,
④其中评论表t_comment的a_id与文章表t_article的主键id相关联
-
新建springboot连接
-
在连接中新建数据库springbootdata
-
在这个数据库中创建两个表:t_article和t_comment
① 总体
② 创建过程
② 创建结果
1.2 创建项目,引入相应启动器,编写实体类
- 创建项目(名为chapter03),依赖选择SQl模块中的MySql和MyBatis依赖。
① MySQL:提供MySQL数据库连接驱动
② MyBatis:提供MyBatis框架来操作数据库
注: 我把默认地址换成了aliyun=>https://start.aliyun.com/
- 编写数据库表对应的实体类:Article和Comment
创建domain包,包内创建两个类
每个实体类都对应一个表
1.3 配置文件=>数据库连接+数据源类型
- 数据库连接配置(在全局配置文件中)=>编写本地MySql数据库(srpngbootdata)的相关配置
- 数据源类型配置
①(这里直接用了这个) 使用阿里巴巴的Druid数据源,需要在pom.xml中添加druid-spring-boot-starter
依赖 => 引入该依赖后,不需要再进行其它额外配置,springboot项目会自动识别配置Druid数据源
② 如果需要修改Druid的运行参数,需要在全局配置文件中修改,并编写自定义配置文件注入这些属性值。因为springboot提供的数据源自动配置类中没有这些配置信息的默认值,所以这些值无法被识别并生效,必须得自己编写一个自定义配置类,然后将配置文件中的属性注入到Druid数据源属性中。
- 数据库连接配置=>在application.properties中配置
密码是自己设置的mysql数据库连接的密码
- 数据源类型选择配置->Druid数据源=>在pom.xml中添加依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
1.3.1演示:修改Druid数据源的参数
这个案例中用了方法一,在pom.xml中引入druid依赖,这里我们演示一下方法二:修改druid数据源参数
- 不要注释掉pom.xml中的druid依赖,在全局配置文件中修改druid运行参数
# 添加并配置第三方数据源
# 修改数据源的类型=>写了这一行,项目才会识别配置的Druid数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化连接数
spring.datasource.initialSize=20
# 最小空闲数
spring.datasource.minIdle=10
# 最大连接数
spring.datasource.maxActive=100
- 编写自定义配置类,对Druid数据源属性值进行注入
新建com.wpz.config包,包中创建DataSourceConfig
①
@Configuration
:把DataSourceConfig标识为自定义配置类
②@Bean
:把DataSource实例对象(new DruidDataSource()
)放到spring容器中 (因为只有这个该对象在容器中(被springboot扫描到),才能进行后续的属性注入操作)
③@ConfigurationProperties(prefix = "spring.datasource")
:将全局配置文件中以spring.datasource
开头的属性值注入到getDataSource()方法返回的DataSource类对象(new DruidDataSource()
)的属性中
package com.wzp.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;
/**
* @author 王胖子
* @version 1.0
* 将全局配置文件中的属性值注入Druid数据源的属性中
*/
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource getDruid() {
return new DruidDataSource();
}
}
2. 使用注解的方式整合MyBatis
2.1 创建并编写Mapper接口文件
创建mapper包,创建Mapper接口文件
编写Mapper接口文件
①
@Mapper
:表示该类是一个MyBatis接口文件,并保证能够被springboot自动扫描到spring容器中
② 在接口内部,通过@Insert、@Update、@Delete、@Select
注解,配合SQL语句
完成对表t_comment数据的增删改查操作
改进:如果编写的Mapper接口过多时,需要重复为每个接口文件添加@Mapper注解,为避免这种麻烦,可以在启动类上添加
@MapperScan("XXX")
,就不需要再逐个添加@Mapper注解,"XXX"指定了需要扫描的具体包名,例如本例中,mapper文件所在的包为com.wpz.mapper,所以就@MapperScan(“com.wpz.mapper”)
2.2 测试方法及测试结果
测试结果为:在数据库中找到id为1的comment信息
3. 使用配置文件的方式整合MyBatis
3.1 创建并编写Mapper接口
mapper包中创建并编写ArticleMapper接口
3.2 创建并编写xml文件
在resources目录下,创建一个mapper包,用于统一管理映射文件,
并在该包下 创建并编写与Mapper接口对应的映射文件ArticleMapper.xml
xml映射文件中通过<mapper>
标签中的<select>、<update>
等标签内的sql语句
对数据进行操作
<?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">
<!--根据接口文件中的方法,编写两个对应的SQL语句-->
<!--namespace的属性值是对应的mapper接口文件的全路径名称-->
<mapper namespace="com.wpz.mapper.ArticleMapper">
<!--1. 查询文章详细(包括评论信息)-->
<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=#{id} AND a.id=c.a_id
</select>
<!--1.1 resultMap中id是唯一的,是resultMap的唯一标识名称 type是里面返回的类型-->
<resultMap id="articleWithComment" type="Article">
<!--1.1.1 id标签表示表的主键-->
<!--1.1.2 column表示数据库的列 property表示实体类的属性-->
<!--这里column中是select查询结果的数据库列的名字,不相交的属性不用写表名-->
<id column="id" property="id"></id>
<!--1.1.3 如果不是主键列,就用result表示-->
<result column="title" property="title"></result>
<result column="content" property="content"></result>
<!--1.1.4 ofType:指的是集合中元素的类型,报错需要加一个javaType -->
<collection property="commentList" ofType="Comment" javaType="java.util.List">
<id column="c_id" property="id"></id>
<result column="c_content" property="content"></result>
<result column="author" property="author"></result>
</collection>
</resultMap>
<!--2. 根据文章id更新文章信息-->
<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>
3.3 配置XML映射文件路径
# 配置MyBatis的XML映射文件路径=>因为springboot扫描不到xml文件,所以要配置
mybatis.mapper-locations=classpath:mapper/*.xml
# 配置XML映射文件中指定的实体类别名路径=>没有使用com.wpz.domain.Article而是使用Article(如果使用全路径,则不用配置了)
mybatis.type-aliases-package=com.wpz.domain
3.4 测试方法及测试结果
package com.wpz;
import com.wpz.domain.Article;
import com.wpz.mapper.ArticleMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Chapter03ApplicationTests {
@Autowired
private ArticleMapper articleMapper;
@Test
public void selectArticle() {
Article article = articleMapper.selectArticle(1);
//这里我为了方便看输出,把Article的toString()中的commentList删掉了,这里用迭代器遍历
System.out.println(article);
Iterator<Comment> iterator = article.getCommentList().iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
}
}
输出结果:
二、两种方式的输出结果
三、整体代码
目录结构
1. 两个实体类
package com.wpz.domain;
import java.util.List;
/**
* @author 王胖子
* @version 1.0
* Article实体类:对应数据库表 t_article => 文章表
*/
public class Article {
private Integer id;//主键id
private String title;//标题
private String content;//内容
private List<Comment> commentList;//该文章的评论集合
//下面是get、set、toString方法
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;
}
}
package com.wpz.domain;
/**
* @author 王胖子
* @version 1.0
* Comment实体类:对应数据库表 t_comment => 评论表
*/
public class Comment {
private Integer id;//主键id
private String content;//评论的内容
private String author;//发表评论的人
private Integer aId;//关联t_article的主键(t_comment的外键)
//下面是get、set、toString方法
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 +
'}';
}
}
2. Mapper接口文件
2.1 使用注解整合MyBatis
package com.wpz.mapper;
import com.wpz.domain.Comment;
import org.apache.ibatis.annotations.*;
/**
* @author 王胖子
* @version 1.0
* 该Mapper接口文件:用于对表t_comment中的数据进行操作
*/
//@Mapper:表示该类是一个MyBatis接口文件,并保证能够被springboot自动扫描到spring容器中
//在接口内部,通过@Insert、@Update、@Delete、@Select注解,配合SQL语句完成对表t_comment数据的增删改查操作
@Mapper
public interface CommentMapper {
//#{id} => 表示传入的id值,id=#{id}为表中的id值与传入参数的id值相等
@Select("SELECT * FROM t_comment WHERE id =#{id}")
Comment findById(Integer id);
@Insert("INSERT INTO t_comment(content,author,a_id)" +
"values (#{content}),(#{author}),(#{a_id})")
int insertComment(Comment comment);
@Update("UPDATE t_comment SET content=#{content} WHERE id=#{id}")
int updateComment(Comment comment);
@Delete("DELETE FROM t_comment WHERE id=#{id}")
int deleteComment(Comment comment);
}
2.2 使用配置文件整合
package com.wpz.mapper;
import com.wpz.domain.Article;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 王胖子
* @version 1.0
* 在mapper包中,创建一个操作表t_article的接口ArticleMapper
*/
@Mapper
public interface ArticleMapper {
//根据文章id查询文章
Article selectArticle(Integer id);
//更新文章,返回更新的条数
int updateArticle(Article article);
}
3. 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">
<!--根据接口文件中的方法,编写两个对应的SQL语句-->
<!--namespace的属性值是对应的mapper接口文件的全路径名称-->
<mapper namespace="com.wpz.mapper.ArticleMapper">
<!--1. 查询文章详细(包括评论信息)-->
<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=#{id} AND a.id=c.a_id
</select>
<!--1.1 resultMap中id是唯一的,是resultMap的唯一标识名称 type是里面返回的类型-->
<resultMap id="articleWithComment" type="Article">
<!--1.1.1 id标签表示表的主键-->
<!--1.1.2 column表示数据库的列 property表示实体类的属性-->
<!--这里column中是select查询结果的数据库列的名字,不相交的属性不用写表名-->
<id column="id" property="id"></id>
<!--1.1.3 如果不是主键列,就用result表示-->
<result column="title" property="title"></result>
<result column="content" property="content"></result>
<!--1.1.4 ofType:指的是集合中元素的类型,报错需要加一个javaType -->
<collection property="commentList" ofType="Comment" javaType="java.util.List">
<id column="c_id" property="id"></id>
<result column="c_content" property="content"></result>
<result column="author" property="author"></result>
</collection>
</resultMap>
<!--2. 根据文章id更新文章信息-->
<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>
4. 测试类
package com.wpz;
import com.wpz.domain.Comment;
import com.wpz.mapper.CommentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.wpz.domain.Article;
import com.wpz.mapper.ArticleMapper;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Iterator;
@SpringBootTest
class Chapter03ApplicationTests {
//测试使用注解整合MyBatis
@Autowired
private CommentMapper commentMapper;
@Test
public void commentTest() {
Comment commentById = commentMapper.findById(1);
System.out.println(commentById);
}
//测试使用配置文件整合MyBatis
@Autowired
private ArticleMapper articleMapper;
@Test
public void selectArticle() {
Article article = articleMapper.selectArticle(1);
//这里我为了方便看输出,把Article的toString()中的commentList删掉了,这里用迭代器遍历
System.out.println(article);
Iterator<Comment> iterator = article.getCommentList().iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
}
}
5. 全局配置文件
# MySQl数据库springbootdata连接配置
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
# 配置MyBatis的XML映射文件路径=>因为springboot扫描不到xml文件,所以要配置
mybatis.mapper-locations=classpath:mapper/*.xml
# 配置XML映射文件中指定的实体类别名路径=>没有使用com.wpz.domain.Article而是使用Article(如果使用全路径,则不用配置了)
mybatis.type-aliases-package=com.wpz.domain
## 添加并配置第三方数据源
## 修改数据源的类型=>写了这一行,项目才会识别配置的Druid数据源
#spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
## 初始化连接数
#spring.datasource.initialSize=20
## 最小空闲数
#spring.datasource.minIdle=10
## 最大连接数
#spring.datasource.maxActive=100
6. 引申:修改Druid数据源的自定义配置类
package com.wpz.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;
/**
* @author 王胖子
* @version 1.0
* 演示修改Druid数据源的参数
* 将全局配置文件中的属性值注入Druid数据源的属性中
*/
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource getDruid() {
return new DruidDataSource();
}
}