前言
原本前些天就已经写好了草稿,但是这两天事情有点多,没有及时发出来哈哈,话不多说,您接着往下瞅。
上个章节介绍了 IDEA 快速构建 SpringBoot 项目。 本章将介绍SpringBoot如何整合其他框架。 下面案例分别为:JUnit、Redis、MyBatis
一、JUnit
简介
JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
JUnit 的优点
1.可以书写一系列的测试方法,对项目所有的接口或者方法进行单元测试。 2.启动后,自动化测试,并判断执行结果, 不需要人为的干预。 3.只需要查看最后结果,就知道整个项目的方法接口是否通畅。 4.每个单元测试用例相对独立,由Junit 启动,自动调用。不需要添加额外的调用语句。 5.添加,删除,屏蔽测试方法,不影响其他的测试方法。 开源框架都对JUnit 有相应的支持。
SpringBoot 整合 JUnit
引入依赖
通过上个章节,我们已经使用 SpringBoot 快速构建项目的方式构建了一个 springBoor-test 项目,构建成功后在 pom.xml 文件中就已经自动引入了 spring-boot-starter-test 起步依赖。 进入该坐标可以发现其内依赖了 JUnit,如此就不需要我们自己再引用其坐标了。
开始使用
在 src -> main -> java 路径下创建User包并创建UserService类并编写测试代码。
@Service
public class UserService {
public void add() {
System.out.println("add()...");
}
}
在 src -> test-> java 路径下创建 user 包并创建 UserServiceTest 测试类用于JUnit 测试。 由于项目构建时 SpringBoot 已经帮我们创建好了对应的测试类,为了演示 @SpringBootTest 注解的 classes 属性,这里建议先创建 user 包下的 UserServiceTest。
@SpringBootTest(classes = SpringBootTestApplication.class)
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void addTest(){
userService.add();
}
}
由于测试类跟引导类不在相同的目录下,所以 @SpringBootTest 注解中需要指定 classes 属性,classes属性的值为当前引导类 SpringBootTestApplication 的字节码文件,也就是SpringBootTestApplication.class. 接下来注入创建好的 UserService,测试 UserService 中的 add() 是否可用。 创建 addTest() 测试方法,在方法顶部添加 @Test 注解,运行方法测试:
说明: @Test 注解依附在 JUnit 的 public void 方法上,表示可以作为一个测试案例。 本注解中有一些比较有意思的属性,比如当我们测试一个方法时,也许它是一个死循环,这样就永远执行不完了,而且可能会导致我们的系统死机,这个时候,我们可以通过 @Test 的属性timeout 来设置运行时间,即可以限定该方法的最大运行时间,如果运行超过了该时间,那么就认为测试是失败的。语法如下:
@Test(timeout=1000)
可以看到,运行测试输出正常。 这时如果我们把 @SpringBootTest 注解中的 classes 属性去除掉,那么启动测试会提示找不到@SpringBootConfiguration。 如果使用项目构建时创建好的测试类,那么就可以不指定 classes 属性,因为该测试类的路径与引导类路径是一样的,在运行时会自动去找引导类。 但是如果我们测试的模块较多,那么就需要把每个模块的测试代码都区分开来,这时,就要用到 classes 属性了。
二、Redis
引言
在 Web 应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候 Web 站点基本上访问和并发不高、交互也较少。而在后来,随着访问量的提升,使用关系型数据库的 Web 站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的 I/O 上。而随着互联网技术的进一步发展,各种类型的应用层出不穷,这导致在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体现在以下四个方面: 1.低延迟的读写速度:应用快速地反应能极大地提升用户的满意度 2.支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和能应对百万级的流量 3.大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理 4.庞大运营成本的考量:IT 部门希望在硬件成本、软件成本和人力成本能够有大幅度地降低 为了克服这一问题,NoSQL 应运而生,它同时具备了高性能、可扩展性强、高可用等优点,受到广泛开发人员和仓库管理人员的青睐。
简介
REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。 Redis 是一个开源的使用 ANSIC 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API。 Redis 通常被称为数据结构服务器,因为值(value)可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。
Redis 的特点
Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 Redis 不仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。 Redis 支持数据的备份,即master-slave模式的数据备份。 Redis 性能极高,Redis能读的速度是110000次/s,写的速度是81000次/s 。 Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。
Redis 的应用场景
Redis 的应用场景包括: 缓存系统(“热点”数据:高频读、低频写)、计数器、消息队列系统、排行榜、社交网络和实时系统。
Redis 的数据类型
Redis 提供的数据类型主要分为5种自有类型。 这5种自有类型包括:String 类型、哈希类型、列表类型、集合类型和顺序集合类型。
String 类型
它是一个二进制安全的字符串,意味着它不仅能够存储字符串、还能存储图片、视频等多种类型, 最大长度支持512M。
哈希类型
该类型是由 field 和关联的 value 组成的 map。其中,field 和 value 都是字符串类型的。
列表类型
该类型是一个插入顺序排序的字符串元素集合, 基于双链表实现。
集合类型
Set 类型是一种无顺序集合, 它和List类型最大的区别是:集合中的元素没有顺序, 且元素是唯一的。 Set 类型的底层是通过哈希表实现的。 Set 类型主要应用于:在某些场景,如社交场景中,通过交集、并集和差集运算,通过 Set 类型可以非常方便地查找共同好友、共同关注和共同偏好等社交关系。
顺序集合类型
ZSet 是一种有序集合类型,每个元素都会关联一个 double 类型的分数权值,通过这个权值来为集合中的成员进行从小到大的排序。与 Set 类型一样,其底层也是通过哈希表实现的。
SpringBoot 整合 Redis
构建项目,引入依赖
使用 SpringBoot 快速构建项目的方式构建一个 springBoot-redis 项目,构建时引入 Redis 的起步依赖,该起步依赖在 NoSQL菜单 下,勾选 Spring Data Redis (Access+Driver) 后单击 Finish 创建项目。 项目创建成功后进入 pom.xml 文件就可以看到 Redis 的起步依赖 spring-boot-starter-data-redis。
开始使用
接下来可以在测试类中编写 Redis 的测试代码。 注入 RedisTemplate 对象并调用方法存入、获取数据。
@Autowired
private RedisTemplate redisTemplate;
@Test
void testSet() {
redisTemplate.boundValueOps("name").set("xinghe");
}
@Test
void testGet() {
Object name = redisTemplate.boundValueOps("name").get();
System.out.println(name);
}
启动本机的 redis-server.exe 并运行测试代码。
以上测试代码中并没有配置 Redis 的相关信息,在程序启动时会自动配置。(只有本机的 Redis 才可以不进行配置,因为 Redis 的连接信息默认为本机的 IP,默认的6379 端口号) 如果想修改 Redis 的配置信息,可以在 application.yml 中进行修改,例如:修改主机 IP 和端口号:
spring:
redis:
host: 127.0.0.1
port: 6379
RedisTemplate 中方法的使用
下面贴一些 RedisTemplate 中一些方法的使用
RedisTemplate 中直接方法
- 删除单个 key
public void delete(String key){
redisTemplate.delete(key);
}
- 删除多个 key
public void deleteKey (String ...keys){
redisTemplate.delete(keys);
}
- 指定 key 的失效时间
public void expire(String key,long time){
redisTemplate.expire(key,time,TimeUnit.MINUTES);
}
- 根据 key 获取过期时间
public long getExpire(String key){
Long expire = redisTemplate.getExpire(key);
return expire;
}
- 判断 key 是否存在
public boolean hasKey(String key){
return redisTemplate.hasKey(key);
}
String 类型相关操作
-
添加缓存
redisTemplate.boundValueOps("StringKey").set("StringValue");
redisTemplate.boundValueOps("StringKey").set("StringValue",1, TimeUnit.MINUTES);
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey");
stringKey.set("StringVaule");
stringKey.set("StringValue",1, TimeUnit.MINUTES);
ValueOperations ops = redisTemplate.opsForValue();
ops.set("StringKey", "StringVaule");
ops.set("StringValue","StringVaule",1, TimeUnit.MINUTES);
-
设置过期时间(单独设置) redisTemplate.boundValueOps("StringKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("StringKey",1,TimeUnit.MINUTES);
-
获取缓存值
String str1 = (String) redisTemplate.boundValueOps("StringKey").get();
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey");
String str2 = (String) stringKey.get();
ValueOperations ops = redisTemplate.opsForValue();
String str3 = (String) ops.get("StringKey");
-
删除 key Boolean result = redisTemplate.delete("StringKey");
-
顺序递增 redisTemplate.boundValueOps("StringKey").increment(3L);
-
顺序递减 redisTemplate.boundValueOps("StringKey").increment(-3L);
Hash 类型相关操作
- 添加缓存
redisTemplate.boundHashOps("HashKey").put("SmallKey", "HashVaue");
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
hashKey.put("SmallKey", "HashVaue");
HashOperations hashOps = redisTemplate.opsForHash();
hashOps.put("HashKey", "SmallKey", "HashVaue");
- 设置过期时间(单独设置)
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("HashKey",1,TimeUnit.MINUTES);
- 添加一个 Map 集合
HashMap<String, String> hashMap = new HashMap<>();
redisTemplate.boundHashOps("HashKey").putAll(hashMap );
- 设置过期时间(单独设置)
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("HashKey",1,TimeUnit.MINUTES);
- 提取所有的小 key
Set keys1 = redisTemplate.boundHashOps("HashKey").keys();
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
Set keys2 = hashKey.keys();
HashOperations hashOps = redisTemplate.opsForHash();
Set keys3 = hashOps.keys("HashKey");
- 提取所有的 value 值
List values1 = redisTemplate.boundHashOps("HashKey").values();
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
List values2 = hashKey.values();
HashOperations hashOps = redisTemplate.opsForHash();
List values3 = hashOps.values("HashKey");
- 根据 key 提取 value 值
String value1 = (String) redisTemplate.boundHashOps("HashKey").get("SmallKey");
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
String value2 = (String) hashKey.get("SmallKey");
HashOperations hashOps = redisTemplate.opsForHash();
String value3 = (String) hashOps.get("HashKey", "SmallKey");
- 获取所有的键值对集合
Map entries = redisTemplate.boundHashOps("HashKey").entries();
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey");
Map entries1 = hashKey.entries();
HashOperations hashOps = redisTemplate.opsForHash();
Map entries2 = hashOps.entries("HashKey");
- 删除
redisTemplate.boundHashOps("HashKey").delete("SmallKey");
redisTemplate.delete("HashKey");
- 判断Hash中是否含有该值
Boolean isEmpty = redisTemplate.boundHashOps("HashKey").hasKey("SmallKey");
LIST 类型相关操作
-
添加缓存
redisTemplate.boundListOps("listKey").leftPush("listLeftValue1");
redisTemplate.boundListOps("listKey").rightPush("listRightValue2");
BoundListOperations listKey = redisTemplate.boundListOps("listKey");
listKey.leftPush("listLeftValue3");
listKey.rightPush("listRightValue4");
ListOperations opsList = redisTemplate.opsForList();
opsList.leftPush("listKey", "listLeftValue5");
opsList.rightPush("listKey", "listRightValue6");
-
将List放入缓存 ArrayList<String> list = new ArrayList<>();
redisTemplate.boundListOps("listKey").rightPushAll(list);
redisTemplate.boundListOps("listKey").leftPushAll(list);
-
设置过期时间(单独设置) redisTemplate.boundValueOps("listKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("listKey",1,TimeUnit.MINUTES);
-
获取 List 缓存全部内容(起始索引,结束索引) List listKey1 = redisTemplate.boundListOps("listKey").range(0, 10);
-
从左或从右弹出一个元素
String listKey2 = (String) redisTemplate.boundListOps("listKey").leftPop();
String listKey3 = (String) redisTemplate.boundListOps("listKey").rightPop();
-
根据索引查询元素 String listKey4 = (String) redisTemplate.boundListOps("listKey").index(1);
-
、获取 List 缓存的长度 Long size = redisTemplate.boundListOps("listKey").size();
-
根据索引修改 List 中的某条数据(key,索引,值) redisTemplate.boundListOps("listKey").set(3L,"listLeftValue3");
-
移除 N 个值为 value (key,移除个数,值) redisTemplate.boundListOps("listKey").remove(3L,"value");
Set类型相关操作
- 添加Set缓存(值可以是一个,也可是多个)
redisTemplate.boundSetOps("setKey").add("setValue1", "setValue2", "setValue3");
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey");
setKey.add("setValue1", "setValue2", "setValue3");
SetOperations setOps = redisTemplate.opsForSet();
setOps.add("setKey", "SetValue1", "setValue2", "setValue3");
- 设置过期时间(单独设置)
redisTemplate.boundValueOps("setKey").expire(1,TimeUnit.MINUTES);
redisTemplate.expire("setKey",1,TimeUnit.MINUTES);
- 根据 key 获取 Set 中的所有值
Set set1 = redisTemplate.boundSetOps("setKey").members();
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey");
Set set2 = setKey.members();
SetOperations setOps = redisTemplate.opsForSet();
Set set3 = setOps.members("setKey");
- 根据 value 从一个 set 中查询,是否存在
Boolean isEmpty = redisTemplate.boundSetOps("setKey").isMember("setValue2");
- 获取 Set 缓存的长度
Long size = redisTemplate.boundSetOps("setKey").size();
- 移除指定的元素
Long result1 = redisTemplate.boundSetOps("setKey").remove("setValue1");
- 移除指定的 key
Boolean result2 = redisTemplate.delete("setKey");
Zset 类型的相关操作
-
向集合中插入元素,并设置分数
redisTemplate.boundZSetOps("zSetKey").add("zSetVaule", 100D);
BoundZSetOperations zSetKey = redisTemplate.boundZSetOps("zSetKey");
zSetKey.add("zSetVaule", 100D);
ZSetOperations zSetOps = redisTemplate.opsForZSet();
zSetOps.add("zSetKey", "zSetVaule", 100D);
-
向集合中插入多个元素,并设置分数 DefaultTypedTuple<String> p1 = new DefaultTypedTuple<>("zSetVaule1", 2.1D);
DefaultTypedTuple<String> p2 = new DefaultTypedTuple<>("zSetVaule2", 3.3D);
redisTemplate.boundZSetOps("zSetKey").add(new HashSet<>(Arrays.asList(p1,p2)));
-
按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部 Set<String> range = redisTemplate.boundZSetOps("zSetKey").range(0, -1);
-
获得指定元素的分数 Double score = redisTemplate.boundZSetOps("zSetKey").score("zSetVaule");
-
返回集合内的成员个数 Long size = redisTemplate.boundZSetOps("zSetKey").size();
-
返回集合内指定分数范围的成员个数(Double 类型) Long COUNT = redisTemplate.boundZSetOps("zSetKey").count(0D, 2.2D);
-
返回集合内元素在指定分数范围内的排名(从小到大) Set byScore = redisTemplate.boundZSetOps("zSetKey").rangeByScore(0D, 2.2D);
-
带偏移量和个数,(key,起始分数,最大分数,偏移量,个数) Set<String> ranking2 = redisTemplate.opsForZSet().rangeByScore("zSetKey", 0D, 2.2D 1, 3);
-
返回集合内元素的排名,以及分数(从小到大) Set<TypedTuple<String>> tuples = redisTemplate.boundZSetOps("zSetKey").rangeWithScores(0L, 3L);
for (TypedTuple<String> tuple : tuples) {
System.out.println(tuple.getValue() + " : " + tuple.getScore());
}
-
返回指定成员的排名
Long startRank = redisTemplate.boundZSetOps("zSetKey").rank("zSetVaule");
Long endRank = redisTemplate.boundZSetOps("zSetKey").reverseRank("zSetVaule");
-
从集合中删除指定元素 redisTemplate.boundZSetOps("zSetKey").remove("zSetVaule");
-
删除指定索引范围的元素(Long 类型) redisTemplate.boundZSetOps("zSetKey").removeRange(0L,3L);
-
删除指定分数范围内的元素(Double类型) redisTemplate.boundZSetOps("zSetKey").removeRangeByScorssse(0D,2.2D);
-
为指定元素加分(Double类型) Double score = redisTemplate.boundZSetOps("zSetKey").incrementScore("zSetVaule",1.1D)
三、MyBatis
引言
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
MyBatis 的特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个 jar 文件+配置几个 SQL 映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:MyBatis 不会对应用程序或者数据库的现有设计强加任何影响。SQL 写在 xml 里,便于统一管理和优化。通过 SQL 语句可以满足操作数据库的所有需求。
- 解除 SQL 与程序代码的耦合:通过提供 DAO 层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。SQL 和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的 orm 字段关系映射。
- 提供对象关系映射标签,支持对象关系组建维护。
- 提供 xml 标签,支持编写动态 SQL。
构建项目,引入依赖
使用 SpringBoot 快速构建项目的方式构建一个springBoor-mybatis 项目,构建时引入 MyBatis 的起步依赖,该起步依赖在 SQL 菜单下,勾选 MyBatis Framework 以及 MySQL 的驱动 MySQL Driver,然后单击 Finish 创建项目。
开始使用
项目创建成功后进入 pom.xml 文件就可以看到 MyBatis 的起步依赖 mybatis-spring-boot-starter。 这个起步依赖与之前的不太相同,它是以 mybatis 开头的依赖,证明它是 mybatis 自己提供的起步依赖,而以spring-boot 开头的起步依赖是 SpringBoot 官方提供的起步依赖,以别的名称开头的都是各自的团队自己提供的。 可以看到 mysql 驱动的 scope 指定为 runtime,意味着当前驱动坐标在编译时是不生效的,在运行时才会生效。 测试之前我们需要导入一下 MySQL 的 SQL 文件以便进行后续的操作。
CREATE DATABASE `springboot` ;
USE `springboot`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
insert into `user`(`id`,`username`,`password`) values (1,'xinghe','123'),(2,'lisi','234');
成功导入 SQL 文件后,需要在 application.yml 配置文件中添加 datasource 的相关配置信息。
spring:
datasource:
url: jdbc:mysql:///springboot?serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
可以看到 driver-calss-name 提示找不到这个驱动,其实是因为在 pom.xml 文件中指定了 mysql 驱动的 scope 为runtime,所以编译时提示找不到驱动,但是运行时没有问题,把这一行注释掉就可以解决这个提示,注释掉之后默认的 scope 是编译时生效。 创建 domain -> User 实体类以及生成 get()、set()、toString() 方法。
package com.springboot.springbootmybatis.domain;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
使用注解 SQL 开发
创建 mapper -> UserMapper,编写查询所有用户的方法,此处使用注解SQL开发的形式。
package com.springboot.springbootmybatis.mapper;
import com.springboot.springbootmybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserMapper {
@Select("select * from user")
public List<User> findAll();
}
接下来就可以在测试类中注入 UserMapper 调用查询所有用户的接口并输出查询到的数据了。
import com.springboot.springbootmybatis.domain.User;
import com.springboot.springbootmybatis.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SpringBootMybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void findAllTest() {
List<User> list = userMapper.findAll();
System.out.println(list);
}
}
运行测试方法,成功输出查询到的用户信息,这里提示警告信息 ”Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class is com.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.” 这个提示代表我们当前使用的驱动版本比较老,建议我们使用 com.mysql.cj.jdbc.Driver 驱动。 可以在 application.yml 配置文件中修改 driver-class-name 就可以消除这个警告信息。
#datasource
spring:
datasource:
url: jdbc:mysql:/
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
使用 XML SQL 开发
创建 mapper -> UserXmlMapper,编写查询所有用户的方法。
package com.springboot.springbootmybatis.mapper;
import com.springboot.springbootmybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface UserXmlMapper {
public List<User> findAll();
}
在 resources 目录下创建 mapper 文件夹,并在文件夹中创建 UserMapper.xml。代码如下:
Mapper 标签里的 namespace 属性与 UserXmlMapper 接口是映射关系,所以需要把 UserXmlMapper 的全路径名赋值给 namespace。
<?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.springboot.springbootmybatis.mapper.UserXmlMapper">
<select id="findAll" resultType="com.springboot.springbootmybatis.domain.User">
SELECT * FROM user
</select>
</mapper>
在 application.yml 配置文件中配置 mybatis 的参数信息
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
type-aliases-package: com.springboo+t.springbootmybatis.domain
配置完成之后就可以在测试类中注入 UserXmlMapper 接口调用 XML 形式的查询方法了。
package com.springboot.springbootmybatis;
import com.springboot.springbootmybatis.domain.User;
import com.springboot.springbootmybatis.mapper.UserMapper;
import com.springboot.springbootmybatis.mapper.UserXmlMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SpringBootMybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Autowired
private UserXmlMapper userXmlMapper;
@Test
void findAllTest() {
List<User> list = userMapper.findAll();
System.out.println(list);
}
@Test
void findAllTest2() {
List<User> list = userXmlMapper.findAll();
System.out.println(list);
}
}
总结
本章介绍了如何使用 SpringBoot 整合 JUint、Redis、 MyBatis 框架,以及如何使用这些框架进行编码。 其中还贴出了部分 Redis 的方法以及 MyBatis 的两种开发模式。 除 MyBatis 外,还有一种 MyBatis Plus 框架,该框架可以节省程序员在进行单表开发时的部分工作量,因为时间关系,本章不再讲解,感兴趣的朋友可以自行研究一下。
|