上一篇文章我们介绍了SpringBoot集成JdbcTemplate.简单体验了一下JdbcTemplate框架的用法,今天的内容比较重要,我们来介绍一下SpringBoot集成Mybatis的步骤。

1、 Mybatis 介绍

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。

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

Mybatis特点:

1、Mybatis实现了接口绑定,使用更加方便。

2、对象关系映射的改进,效率更高

3、MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。

优点:

1、简单易学

mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

2、灵活

mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。

3、解除sql与程序代码的耦合

通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

4、提供映射标签,支持对象与数据库的orm字段关系映射

5、提供对象关系映射标签,支持对象关系组建维护

6、提供xml标签,支持编写动态sql。

缺点:

1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。

2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。

3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。

4、二级缓存机制不佳

上面的内容都是从网上拷贝的,因为我想大多数的人应该都用过mybatis,并且我们本文的侧重点主要是SpringBoot的集成方式,而不是从头介绍Mybatis,如果大家对Mybatis的使用不太了解,建议先去学习一下Mybatis的用法。

2、集成步骤

接下来我们开始进行集成。为了方便操作,由于我们上次刚刚集成过JdbcTemplate, 代码中共存多个DAO层框架可能会有问题,我们在原有项目基础上拉取一个新的分支来进行开发,分支名就叫 feature/mybaits。完成的代码都会托管到gitCode上,大家可在文末获取地址。

2.1 引入依赖

首先我们先引入Mybatis所需依赖,mybatis本身已经提供了用于适配springBoot的Starter, 同时我们还需要引入 mysql-connector. 在pom.xml中添加:

<!-- lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version><scope>provided</scope>
</dependency><!-- mybatis-spring-boot-starter -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.1</version>
</dependency><!-- MySQL连接 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>

2.2 配置数据库连接

在spring的配置文件中,配置我们需要访问的数据库的连接信息,这个配置和前面jdbcTemplate的配置一样

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springboot_learningusername: rootpassword: root

2.3 开发Mapper

在JdbcTemplate中我们访问数据库的这一层使用dao表示的。但是在mybatis中,我们一般都把这一层称之为mapper, 并且一般类名也用这个结尾,其实代表的都是一个意思,就是使用习惯的问题。在Mybatis中的Mapper也是分为接口和实现,比较特殊的是mapper的实现一般使用xml文件的形式来体现。我们的sql也都是写在xml文件中。

我们在项目中创建一个mapper的文件夹,用来存放所有的Mapper接口。我们在里边创建UserMapper用来处理user表的增删改查操作。

@Mapper
public interface UserMapper {/*** 删除操作* @param id* @return*/int deleteByPrimaryKey(Integer id);/*** 插入操作* @param record* @return*/int insert(User record);/*** 插如操作* @param record* @return*/int insertSelective(User record);/*** 根据id查询操作* @param id* @return*/User selectByPrimaryKey(Integer id);/*** 更新操作* @param record* @return*/int updateByPrimaryKeySelective(User record);/*** 更新操作* @param record* @return*/int updateByPrimaryKey(User record);
}

然后在resources 资源目录下(application.yml同级目录下)创建一个mapper文件夹,用于存放xml格式的mapper实现。在里面写一个UserMapper.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.lsqingfeng.springboot.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.lsqingfeng.springboot.entity.User"><id column="id" jdbcType="INTEGER" property="id" /><result column="name" jdbcType="VARCHAR" property="name" /><result column="age" jdbcType="INTEGER" property="age" /><result column="address" jdbcType="VARCHAR" property="address" /><result column="create_time" jdbcType="TIMESTAMP" property="createTime" /><result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /></resultMap><!--sql语句片段,将公共部分抽出--><sql id="Base_Column_List">id, name, age,address,create_time, update_time</sql><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">select<include refid="Base_Column_List" />from t_userwhere id = #{id,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">delete from t_userwhere id = #{id,jdbcType=INTEGER}</delete><insert id="insert" parameterType="com.lsqingfeng.springboot.entity.User">insert into t_user ( name, age,address,create_time ,update_time)values (#{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER},#{address},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert><!--动态sql--><insert id="insertSelective" parameterType="com.lsqingfeng.springboot.entity.User">insert into t_user<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="name != null">name,</if><if test="age != null">age,</if><if test="address != null">address,</if><if test="createTime != null">create_time,</if><if test="updateTime != null">update_time,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=INTEGER},</if><if test="name != null">#{name,jdbcType=VARCHAR},</if><if test="age != null">#{age,jdbcType=INTEGER},</if><if test="address != null">#{address},</if><if test="updateTime != null">#{createTime,jdbcType=TIMESTAMP},</if><if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if></trim></insert><update id="updateByPrimaryKeySelective" parameterType="com.lsqingfeng.springboot.entity.User">update t_user<set><if test="name != null">name = #{name,jdbcType=VARCHAR},</if><if test="age != null">age = #{age,jdbcType=INTEGER},</if><if test="address != null">address = #{address},</if><if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if><if test="age != null">update_time = #{updateTime,jdbcType=TIMESTAMP}</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.lsqingfeng.springboot.entity.User">update t_userset name = #{name,jdbcType=VARCHAR},age = #{age,jdbcType=INTEGER},address = #{address,jdbcType=VARCHAR},create_time = #{createTime,jdbcType=TIMESTAMP},update_time = #{updateTime,jdbcType=TIMESTAMP}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

然后在Service层中引用mapper.

2.4 配置Mapper的路径

我们现在是把xml类型的文件都放在了resources下的mapper文件夹中了。但是这个路径对与我们的项目中的mybatis来说他是不知道的,所以我们需要告诉它这个路径的位置。怎么告诉呢,就是在application.yml中配置一下。

mybatis:mapper-locations: classpath:mapper/*.xml

mapper的位置位于 classpath下的mapper文件夹中的所有xml结尾的文件。

这里还有一个问题也提下。就是mapper的接口的位置我们并没有配置,他是怎么知道的呢,其实是我们在每个Mapper的接口上都加上了@Mapper的注解,所以他可以自动扫描到。如果要加这个注解,那么所有的Mapper接口上就都需要加,这其实是比较麻烦的。怎么办呢,我们可以都不加这个注解,然后在SpringBoot的启动类上,加上一个MapperScan注解,将mapper的包路径配置进去,就都不用加了。

我们去掉@Mapper注解,也不加任何配置会报错:

我们在主类上添加注解:

@SpringBootApplication
@MapperScan("com.lsqingfeng.springboot.mapper")
public class SpringBootLearningApplication {public static void main(String[] args) {SpringApplication.run(SpringBootLearningApplication.class, args);}
}

再次启动:

成功了。

3、 接口测试

组装好项目后,我们来调用一下接口。继续使用之前的jdbc里写好的Controller进行测试。

调用成功后,观察数据库。

李四这条使我们刚刚插入进去的,只不过两个时间是空值,因为我们并没有给时间赋值。

再看看查询接口。

4、mybatis自动填充时间

上面的案例中,由于我们没有对时间进行设置,导致创建时间和修改时间都是空的。其实Mybatis中为我们提供了拦截器的机制,相当于可以对每次执行的sql进行拦截,这样我们就可以对对操作进行判断,如果是插入操作,就直接设置创建时间和修改时间为当前时间。如果是更新操作则设置更新时间为当前时间。

拦截器代码如下。

import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Date;/*** Mybatis拦截器,用能与设置创建时间和更新时间*/
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class CreateTimeSetInterceptor implements Interceptor {private static final String CREATE_TIME_SETTER = "setCreateTime";private static final String UPDATE_TIME_SETTER = "setUpdateTime";@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement ms = (MappedStatement) invocation.getArgs()[0];Object parameter = invocation.getArgs()[1];if (ms.getSqlCommandType() == SqlCommandType.INSERT) {setTimeIfNeccesary(parameter, CREATE_TIME_SETTER);setTimeIfNeccesary(parameter, UPDATE_TIME_SETTER);} else if (ms.getSqlCommandType() == SqlCommandType.UPDATE) {setTimeIfNeccesary(parameter, UPDATE_TIME_SETTER);}return invocation.getMethod().invoke(invocation.getTarget(), invocation.getArgs());}private void setTimeIfNeccesary(Object param, String methodName) {Class<?> cls = param.getClass();if (cls == ParamMap.class) {@SuppressWarnings("unchecked")ParamMap<Object> map = (ParamMap<Object>) param;map.entrySet().forEach(entry -> {if (!entry.getKey().equals("et")) {setIfSetterExist(entry.getValue(), methodName);}});} else {setIfSetterExist(param, methodName);}}private void setIfSetterExist(Object param, String methodName) {Class<?> cls = param.getClass();try {Method m = null;try {m = cls.getDeclaredMethod(methodName, new Class[] { Date.class });if (m != null) {m.setAccessible(true);m.invoke(param, new Date());}} catch (NoSuchMethodException e1) {m = cls.getDeclaredMethod(methodName, new Class[] { Timestamp.class });if (m != null) {m.setAccessible(true);m.invoke(param, new Timestamp(System.currentTimeMillis()));}}} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException| InvocationTargetException e) {e.printStackTrace();}}}

接下来我们再来执行一个插入操作》

再次观察数据库:

发现时间已经有值了。

5、 mybatis-generator 插件

我们上面通过User表创建了UserMapper接口和UserMapper的xml实现。其实这类文件中的内容是比较有规律的,所以如果每次没有都去自己写,是比较耗费时间的,所有mybatis为我们提供了mybatis-generator插件,通过这个插件,我们可以设置对应的数据库连接和表名,然后插件就会帮我们自动生成对应的实体,mapper接口和Mapper实现,里面的方法只有常用的增删改查操作。能够大大较少我们操作的工作量。 这个步骤,我们一般称之为 mybatis 逆向生成。 逆向生成的方法比较多,有兴趣的自己去找找吧,这里不想展开了,因为现在随着mybatisPlus的普及,使用mybatis-plus-generator的更多一些。

好了关于SpringBoot集成Mybatis我们就介绍这么多。欢迎大家一起交流,有问题随时留言。

另: 配套项目代码已托管中gitCode: gitcode.net/lsqingfeng/…

所有文章也会在微信公众号首发更新,欢迎关注: 一缕82年的清风

SpringBoot教程(十一) | SpringBoot集成Mybatis相关推荐

  1. SpringBoot(13)--- 数据库操作(集成MyBatis)

    SpringBoot 数据库操作(集成MyBatis) Spring对持久化的支持,不单只支持JDBC,为各种支持的持久化技术都提供了简单的模板和回调: ORM持久化技术 模板类 JDBC(JdbcT ...

  2. SpringBoot教程(十一)——将Bean放入Spring容器中的五种方式

    将bean放入Spring容器中有哪些方式? 我们知道平时在开发中使用Spring的时候,都是将对象交由Spring去管理,那么将一个对象加入到Spring容器中,有哪些方式呢,下面我就来总结一下 1 ...

  3. idal 创建springboot 项目_手把手的SpringBoot教程,SpringBoot创建web项目(四)

    在实际的开发过程中,我们需要前端页面向Java端提交请求,这些请求一般分为get方式和post方式,不管是哪一种方式,一般都会携带一些参数.这一节,我们来演示一下如何给Controller传递参数. ...

  4. SpringBoot教程(二)|SpringBoot项目配置数据库

    1.导入依赖 搭建是Springboot可以看我上一篇  使用maven搭建Springboot 在pom.xml中添加mysql连接需要的依赖 <dependency><group ...

  5. 【SpringBoot教程】SpringBoot开发HTTP接口GET请求实战

    ⛪ 专栏地址 系列教程更新中

  6. 通俗易懂的SpringBoot教程---day2---Springboot配置文件

    通俗易懂的SpringBoot教程-day2-Springboot配置文件 1.配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.propertie ...

  7. springboot 集成mybatis_SpringBoot快速集成Mybatis并轻松上手调试教程,请查收!

    本篇主题:SpringBoot如何快速集成Mybatis并上手调试? 引入相关Jar依赖 这里使用Gradle作为构建工具,构建脚本build.gradle见下图: build.gradle 事实上, ...

  8. SpringBoot图文教程8 — SpringBoot集成MBG「代码生成器」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

  9. springboot集成swagger2多模块中文配置详细步骤,解决集成mybatis或mybatis-plus无法正常使用问题

    springboot集成swagger2多模块中文配置详细步骤,解决集成mybatis或mybatis-plus无法正常使用问题 参考文章: (1)springboot集成swagger2多模块中文配 ...

最新文章

  1. 使用PowerShell 监控运行时间和连接情况
  2. Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)
  3. 《深入理解 Java 内存模型》读书笔记(下)(干货,万字长文)
  4. hibernate教程--检索方式(hql,sql,QBC)
  5. python 测试用例怎么输入两个_python selenium多个测试用例
  6. Asp.Net Web API 2第七课——Web API异常处理
  7. 4bit超前进位加法器电路
  8. 微软正式发布Azure Functions 2.0
  9. html ie 版本设置密码,如何给IE浏览器设置一个密码的详细图文步骤
  10. c# Open Source
  11. -bash: pip: command not found错误
  12. oracle的用户和mysql的用户_oracle数据库的用户以及表空间
  13. C语言使用scanf_s函数输入的正确姿势
  14. 简单图片隐写术练习题
  15. python结巴怎么安装_Python3.6 结巴分词安装和使用
  16. 利用Jupyter Notebook进行科学计算和数据分析
  17. swiper(轮播图)基本使用
  18. sentry mysql_Apache Sentry安装及简单使用
  19. 基于python的火车票售票系统/基于django火车票务网站/火车购票系统
  20. JavaScript趣味编程--仿微信飞机大战游戏--1.画飞机

热门文章

  1. Android中Canvas和Paint的常用方法
  2. flask上传图片以及生成缩略图
  3. 电脑录麦克风声音软件的选择
  4. 在Unity实现Canny边缘检测
  5. 计算机系统中软件的分类及各自的定义,计算机软件的定义和分类
  6. NOIP2018提高组 货币系统
  7. file upload 攻防世界_菜鸡 CTF 之旅 Writeup (攻防世界)
  8. 【网络经济与企业管理】选择题,错题
  9. 显示技术全倒装COB小间距LED与正装COB小间距的优势对比。
  10. 每天一个小技巧——网易邮箱配置阿里云企业邮箱配置信息设置