Spring Boot2 系列教程(二十一)整合 MyBatis
前面两篇文章和读者聊了 Spring Boot 中最简单的数据持久化方案 JdbcTemplate,JdbcTemplate 虽然简单,但是用的并不多,因为它没有 MyBatis 方便,在 Spring+SpringMVC 中整合 MyBatis 步骤还是有点复杂的,要配置多个 Bean,Spring Boot 中对此做了进一步的简化,使 MyBatis 基本上可以做到开箱即用,本文就来看看在 Spring Boot 中 MyBatis 要如何使用。
工程创建
首先创建一个基本的 Spring Boot 工程,添加 Web 依赖,MyBatis 依赖以及 MySQL 驱动依赖,如下:
创建成功后,添加Druid依赖,并且锁定MySQL驱动版本,完整的依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.28</version>
<scope>runtime</scope>
</dependency>
如此,工程就算是创建成功了。小伙伴们注意,MyBatis 和 Druid 依赖的命名和其他库的命名不太一样,是属于 xxx-spring-boot-stater 模式的,这表示该 starter 是由第三方提供的。
基本用法
MyBatis 的使用和 JdbcTemplate 基本一致,首先也是在 application.properties 中配置数据库的基本信息:
spring.datasource.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
配置完成后,MyBatis 就可以创建 Mapper 来使用了,例如我这里直接创建一个 UserMapper2,如下:
public interface UserMapper2 {
@Select("select * from user")
List<User> getAllUsers();
@Results({
@Result(property = "id", column = "id"),
@Result(property = "username", column = "u"),
@Result(property = "address", column = "a")
})
@Select("select username as u,address as a,id as id from user where id=#{id}")
User getUserById(Long id);
@Select("select * from user where username like concat('%',#{name},'%')")
List<User> getUsersByName(String name);
@Insert({"insert into user(username,address) values(#{username},#{address})"})
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", before = false, resultType = Integer.class)
Integer addUser(User user);
@Update("update user set username=#{username},address=#{address} where id=#{id}")
Integer updateUserById(User user);
@Delete("delete from user where id=#{id}")
Integer deleteUserById(Integer id);
}
这里是通过全注解的方式来写 SQL,不写 XML 文件。
@Select、@Insert、@Update 以及 @Delete 四个注解分别对应 XML 中的 select、insert、update 以及 delete 标签,@Results 注解类似于 XML 中的 ResultMap 映射文件(getUserById 方法给查询结果的字段取别名主要是向小伙伴们演示下 @Results
注解的用法)。
另外使用 @SelectKey 注解可以实现主键回填的功能,即当数据插入成功后,插入成功的数据 id 会赋值到 user 对象的id 属性上。
UserMapper2 创建好之后,还要配置 mapper 扫描,有两种方式,一种是直接在 UserMapper2 上面添加 @Mapper
注解,这种方式有一个弊端就是所有的 Mapper 都要手动添加,要是落下一个就会报错,还有一个一劳永逸的办法就是直接在启动类上添加 Mapper 扫描,如下:
@SpringBootApplication
@MapperScan(basePackages = "org.javaboy.mybatis.mapper")
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class, args);
}
}
好了,做完这些工作就可以去测试 Mapper 的使用了。
mapper 映射
当然,开发者也可以在 XML 中写 SQL,例如创建一个 UserMapper,如下:
public interface UserMapper {
List<User> getAllUser();
Integer addUser(User user);
Integer updateUserById(User user);
Integer deleteUserById(Integer id);
}
然后创建 UserMapper.xml 文件,如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-21-mapper.dtd">
<mapper namespace="org.javaboy.mybatis.mapper.UserMapper">
<select id="getAllUser" resultType="org.javaboy.mybatis.model.User">
select * from t_user;
</select>
<insert id="addUser" parameterType="org.javaboy.mybatis.model.User">
insert into user (username,address) values (#{username},#{address});
</insert>
<update id="updateUserById" parameterType="org.javaboy.mybatis.model.User">
update user set username=#{username},address=#{address} where id=#{id}
</update>
<delete id="deleteUserById">
delete from user where id=#{id}
</delete>
</mapper>
将接口中方法对应的 SQL 直接写在 XML 文件中。
那么这个 UserMapper.xml 到底放在哪里呢?有两个位置可以放,第一个是直接放在 UserMapper 所在的包下面:
放在这里的 UserMapper.xml 会被自动扫描到,但是有另外一个 Maven 带来的问题,就是 java 目录下的 xml 资源在项目打包时会被忽略掉,所以,如果 UserMapper.xml 放在包下,需要在 pom.xml 文件中再添加如下配置,避免打包时 java 目录下的 XML 文件被自动忽略掉:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
当然,UserMapper.xml 也可以直接放在 resources 目录下,这样就不用担心打包时被忽略了,但是放在 resources 目录下,必须创建和 Mapper 接口包目录相同的目录层级,这样才能确保打包后 XML 和 Mapper 接口又处于在一起,否则 XML 文件将不能被自动扫描,这个时候就需要添加额外配置。例如我在 resources 目录下创建 mapper 目录用来放 mapper 文件,如下:
此时在 application.properties 中告诉 mybatis 去哪里扫描 mapper:
mybatis.mapper-locations=classpath:mapper/*.xml
如此配置之后,mapper 就可以正常使用了。注意这种方式不需要在 pom.xml 文件中配置文件过滤。
原理分析
在 SSM 整合中,开发者需要自己提供两个 Bean,一个SqlSessionFactoryBean ,还有一个是 MapperScannerConfigurer,在 Spring Boot 中,这两个东西虽然不用开发者自己提供了,但是并不意味着这两个 Bean 不需要了,在 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
类中,我们可以看到 Spring Boot 提供了这两个 Bean,部分源码如下:
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
return factory.getObject();
}
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
ExecutorType executorType = this.properties.getExecutorType();
if (executorType != null) {
return new SqlSessionTemplate(sqlSessionFactory, executorType);
} else {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@org.springframework.context.annotation.Configuration
@Import({ AutoConfiguredMapperScannerRegistrar.class })
@ConditionalOnMissingBean(MapperFactoryBean.class)
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() {
logger.debug("No {} found.", MapperFactoryBean.class.getName());
}
}
}
从类上的注解可以看出,当当前类路径下存在 SqlSessionFactory、 SqlSessionFactoryBean 以及 DataSource 时,这里的配置才会生效,SqlSessionFactory 和 SqlTemplate 都被提供了。为什么要看这段代码呢?下篇文章,松哥和大伙分享 Spring Boot 中 MyBatis 多数据源的配置时,这里将是一个重要的参考。
好了,本文就先说到这里,本文相关案例,大家可以在 GitHub 上下载:https://github.com/lenve/javaboy-code-samples
关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!
Spring Boot2 系列教程(二十一)整合 MyBatis的更多相关文章
- Spring Boot2 系列教程 (九) | SpringBoot 整合 Mybatis
前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,本文通过注解的形式实现. 什么是 Mybatis MyBatis 是支持定制化 SQL.存储过程以及 ...
- Spring Boot2 系列教程(二十)Spring Boot 整合JdbcTemplate 多数据源
多数据源配置也算是一个常见的开发需求,Spring 和 SpringBoot 中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,我还是建议首选分布式数据库中间件 MyCat 去解决相关问 ...
- Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
本文是 Spring Boot 整合数据持久化方案的最后一篇,主要和大伙来聊聊 Spring Boot 整合 Jpa 多数据源问题.在 Spring Boot 整合JbdcTemplate 多数据源. ...
- Spring Boot2 系列教程(二十六)Spring Boot 整合 Redis
在 Redis 出现之前,我们的缓存框架各种各样,有了 Redis ,缓存方案基本上都统一了,关于 Redis,松哥之前有一个系列教程,尚不了解 Redis 的小伙伴可以参考这个教程: Redis 教 ...
- Spring Boot2 系列教程(二十八)Spring Boot 整合 Session 共享
这篇文章是松哥的原创,但是在第一次发布的时候,忘了标记原创,结果被好多号转发,导致我后来整理的时候自己没法标记原创了.写了几百篇原创技术干货了,有一两篇忘记标记原创进而造成的一点点小小损失也能接受,不 ...
- Spring Boot2 系列教程(二)创建 Spring Boot 项目的三种方式
我最早是 2016 年底开始写 Spring Boot 相关的博客,当时使用的版本还是 1.4.x ,文章发表在 CSDN 上,阅读量最大的一篇有 43W+,如下图: 2017 年由于种种原因,就没有 ...
- Spring Boot2 系列教程(二十二)整合 MyBatis 多数据源
关于多数据源的配置,前面和大伙介绍过 JdbcTemplate 多数据源配置,那个比较简单,本文来和大伙说说 MyBatis 多数据源的配置. 其实关于多数据源,我的态度还是和之前一样,复杂的就直接上 ...
- Spring Boot2 系列教程(二十四)Spring Boot 整合 Jpa
Spring Boot 中的数据持久化方案前面给大伙介绍了两种了,一个是 JdbcTemplate,还有一个 MyBatis,JdbcTemplate 配置简单,使用也简单,但是功能也非常有限,MyB ...
- Spring Boot2 系列教程(二十九)Spring Boot 整合 Redis
经过 Spring Boot 的整合封装与自动化配置,在 Spring Boot 中整合Redis 已经变得非常容易了,开发者只需要引入 Spring Data Redis 依赖,然后简单配下 red ...
随机推荐
- Java匹马行天下之教你用学汉语式方法学编程语言
Java匹马行天下之教你用学汉语式方法学编程语言 前言: 前段时间接连更新了带小白从入门到了解的几篇博客: <Java匹马行天下之编程常识知多少> <Java匹马行天下之走进编程的殿 ...
- spring-data-redis-cache 使用及源码走读
预期读者 准备使用 spring 的 data-redis-cache 的同学 了解 @CacheConfig,@Cacheable,@CachePut,@CacheEvict,@Caching 的使 ...
- 31、vue-cli3引入封装svg图标
svg图标放大不失真,png会出现失真现象. 一.方法一 1.在对应vue项目里添加插件 vue add svg-sprite 输入 Y 2.在执行 npm install svgo svgo-loa ...
- Vue入门教程 第二篇 (数据绑定与响应式)
数据绑定 Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统: <div id="app"> {{ message }} </ ...
- python编程基础之二十
字符串的其他常用方法: ord(char) # 返回char字符对应的码值,可以是中文字符 chr(x) # 输入一个unicode码,返回对应的字符 eval(str) # 将str 中的内容 ...
- 从输入URL到页面渲染完成 -戈多编程
1.输入URL地址 2.浏览器根据域名查询IP地址 3.浏览器发送HTTP请求到web服务器 4.服务器返回一个永久重定向响应 5.浏览器会跟踪重定向地址 6.服务器处理请求 7.服务器返回一个HTM ...
- Map集合(双列集合)
Map集合(双列集合)Map集合是键值对集合. 它的元素是由两个值组成的,元素的格式是:key=value. Map集合形式:{key1=value1 , key2=value2 , key3=val ...
- luoguP4779 【模板】单源最短路径
题目描述 单源最短路径模板. 使用 SPFA 肯定是不行的啦,网格图hack. 所以我们使用 Dijkstra 算法. 这里有一篇写的很好的 blog,无必要赘述.最后贴上代码. #include&l ...
- 【Dubbo】Zookeeper+Dubbo项目demo搭建
一.Dubbo的注解配置 在Dubbo 2.6.3及以上版本提供支持. 1.@Service(全路径@org.apache.dubbo.config.annotation.Service) 配置服务提 ...
- Rsync服务常见问题
转---Rsync 故障排查整理 Rsync服务常见问题汇总讲解: 1. 客户端的错误现象:No route to host rsync服务端开启的iptables**防火墙** [root@nfs0 ...