1 概述

MyBaits是一个著名的持久层框架,本文首先介绍了MyBatis的简单使用,接着与Spring进行整合,最后简单地使用了Generator去自动生成代码。

2 MyBatis简介

MyBatis本来是Apache的一个开源项目——iBatis,2010年由Apaceh Software Foundation迁移到了Google Code,并改名为MyBatis

MyBatis是一个基于Java的持久层框架,提供的持久层框架包括SQL MapsData Access Objects,使用简单的XML或者注解用于配置映射,将接口和POJO映射成数据库中的记录,是一个小巧、方便、高效、简单、直接、半自动化的持久层框架。

3 工作原理

上图:

  • 读取配置文件:mybatis-config.xml是全局MyBatis配置文件,配置了MyBatis运行环境信息
  • 加载映射文件:也就是SQL映射文件,配置了操作数据库的SQL语句
  • 构造会话工厂:通过配置文件构造会话工厂SqlSessionFactory
  • 创建会话对象:由上一步的会话工厂创建会话对象SqlSession
  • 获取MapperStatement:通过用户调用的apiStatement ID获取MapperStatement对象
  • 输入参数映射:通过ExecutorMapperStatement进行解析,将各种Java基本类型转化为SQL操作语句中的类型
  • 输出结果映射:JDBC执行SQL后,借助MapperStatement的映射关系将返回结果转化为Java基本类型并返回

4 MyBatis示例

首先先来看一下纯MyBaits的示例,没有整合Spring,一个简单的Maven工程,项目结构如下:

4.1 依赖

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency> <!--驱动用的是MySQL,版本请自行修改-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>

Gradle

compile group: 'org.mybatis', name: 'mybatis', version: '3.5.5'
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21'

4.2 实体类

@Setter
@Getter
@Builder
public class User {
private Integer id;
private String name; @Override
public String toString() {
return "id:"+id+"\tname:"+name;
}
}

4.3 映射文件

新建一个叫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="UserMapper">
<select id="selectById" parameterType="Integer" resultType="pers.entity.User">
select * from user where id=#{id}
</select>
<select id="selectAll" resultType="pers.entity.User">
select * from user
</select> <insert id="insert" parameterType="pers.entity.User">
INSERT INTO `user` (`id`,`name`)
VALUES (#{id},#{name})
</insert> <update id="update" parameterType="pers.entity.User">
UPDATE `user` set `name`=#{name} where id=#{id}
</update> <delete id="delete" parameterType="Integer">
DELETE FROM `user` WHERE `id` = #{id}
</delete>
</mapper>

映射文件是一个XML文件,根元素为<mapper>,需要注意其中的namespace属性,调用的时候通过该namespace调用。其中的子元素表示SQL语句:

  • <select>:查询,id指定了这条语句的id号,调用时通过namespace.id的方式调用,比如该条select需要通过UserMapper.selectById调用,parameterType指定参数类型,这里是一个Integer的参数,resultType指定返回类型,实体类
  • <insert>/<update>/<delete>:对应的插入/修改/删除语句
  • 关于占位符:#{}表示是占位符,相当于传统JDBC中的?#{id}表示该占位符等待接收的参数名称为id

4.4 配置文件

MyBatis的配置文件,叫mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>

指定了数据库的一些连接属性还有mapper的位置。

4.5 测试

public class Main {
public static void main(String[] args) {
try
{
InputStream inputStream = Resources.getResourceAsStream("config/mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = factory.openSession();
User user = session.selectOne("UserMapper.selectById",1);
System.out.println(user);
User user1 = User.builder().name("test").build();
session.insert("UserMapper.insert",user1);
user1.setName("222");
session.update("UserMapper.update",user1);
List<User> list = session.selectList("UserMapper.selectAll");
list.forEach(System.out::println);
session.delete("UserMapper.delete",1);
session.commit();
session.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

主要流程如下:

  • 读取配置文件:根据org.apache.ibatis.io.Resources读取配置文件mybatis-config.xml,请注意配置文件的位置正确,这里的配置文件都放在resources下,mybatis-config.xml放在其中的config
  • 构建Session:根据配置文件构建SqlSessionFactory后,通过openSession创建Session
  • 业务操作:通过sessionselectOne/insert/update等进行业务操作,这类操作带两个参数,第一个参数是String,表示配置文件中的SQL语句,采用namespace.id的形式,比如这里的UserMapper.xml中声明namespaceUserMapper,其中带有一条idselectByIdselect语句,因此调用时使用UserMapper.selectById的形式,第二个参数是一个Object,表示要传递的参数,也就是绑定到配置文件中对应占位符的值
  • 提交与关闭:业务操作完成后提交事务并关闭session

示例测试结果:

5 Spring整合示例

上面的例子只是为了演示MyBatis的基本使用,没有整合Spring,这里的例子是把Spring整合进来,流程也大概差不多,项目结构如下:

5.1 依赖

分为5类JAR

  • MyBatis需要的JAR
  • Spring需要的JAR
  • MyBatisSpring整合的中间JAR
  • 数据库驱动JAR
  • 数据源JAR

完整依赖如下:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.9.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.9.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.9.RELEASE</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.9.RELEASE</version>
</dependency> <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency> <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.8.0</version>
</dependency>

Gradle

compile group: 'org.springframework', name: 'spring-beans', version: '5.2.9.RELEASE'
compile group: 'org.springframework', name: 'spring-context', version: '5.2.9.RELEASE'
compile group: 'org.springframework', name: 'spring-core', version: '5.2.9.RELEASE'
compile group: 'org.springframework', name: 'spring-tx', version: '5.2.9.RELEASE'
compile group: 'org.springframework', name: 'spring-jdbc', version: '5.2.9.RELEASE'
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21'
compile group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.8.0'
compile group: 'org.mybatis', name: 'mybatis', version: '3.5.5'
compile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.5'

5.2 配置文件

配置文件分为三类:

  • MyBatis映射文件:编写mapper的地方,也就是业务需要的SQL语句
  • MyBatis全局配置文件:由于整合了Spring,数据源的配置放在了Spring的配置文件中,而只需要保留mapper的查找位置
  • Spring配置文件:配置数据源+事务管理+MyBaitssqlSssionFactory+组件扫描

5.2.1 MyBatis映射文件

与上面的例子差不多,只是修改了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="pers.dao.UserDao">
<select id="selectById" parameterType="Integer" resultType="pers.entity.User">
select * from user where id=#{id}
</select>
<select id="selectAll" resultType="pers.entity.User">
select * from user
</select> <insert id="insert" parameterType="pers.entity.User">
INSERT INTO `user` (`id`,`name`)
VALUES (#{id},#{name})
</insert> <update id="update" parameterType="pers.entity.User">
UPDATE `user` set `name`=#{name} where id=#{id}
</update> <delete id="delete" parameterType="Integer">
DELETE FROM `user` WHERE `id` = #{id}
</delete>
</mapper>

namespace需要与对应包名的带有@Mapper的类配置一致。

5.2.2 MyBatis配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>

5.2.3 Spring配置文件

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd"
> <context:component-scan base-package="pers.dao"/>
<context:component-scan base-package="pers.service"/>
<!--数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
<!--最大连接数+最大空闲数+初始连接数-->
<property name="maxTotal" value="30"/>
<property name="maxIdle" value="10"/>
<property name="initialSize" value="5"/>
</bean> <!--事务管理-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <!--开启事务注解-->
<tx:annotation-driven transaction-manager="txManager" /> <!--创建SqlSessionFactory Bean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:config/mybatis-config.xml"/>
</bean> <!--注解扫描,主要用于@Mapper,会扫描basePackge下的@Mapper注解的接口并自动装配为MyBatis的映射接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="pers.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
</beans>

5.3 持久层

需要加上@Mapper注解,表示自动装配为MyBatis的映射接口,注意:

  • 映射文件中的namespace需要与包名.类名对应,比如这里的包为pers.dao,类名为UserDao,那么映射文件中的namespacepers.dao.UserDao
  • id需要与方法名对应,比如映射文件中的有一条select语句的idselectById,那么方法就需要命名为selectById,且参数类型需要对应一致
@Repository
@Mapper
public interface UserDao {
User selectById(Integer id);
List<User> selectAll();
int insert(User user);
int update(User user);
int delete(Integer id);
}

5.4 业务层

@Service
@Transactional
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MyBatisService {
private final UserDao dao; public void test(){
User user = dao.selectById(13);
System.out.println(user);
dao.insert(User.builder().name("333").build());
dao.update(User.builder().name("88888").id(13).build());
dao.selectAll().forEach(System.out::println);
dao.delete(12);
dao.selectAll().forEach(System.out::println);
}
}

注入UserDao后进行简单的测试,结果如下:

6 自动生成代码

相信很多程序员也讨厌写又长又麻烦的XML配置文件,因此,MyBatis也提供了一个生成器插件,可以直接从表中生成实体类、dao接口以及映射文件,可以省去很多操作。

步骤如下:

  • 导入依赖
  • 编写Generator配置文件
  • 生成代码

6.1 依赖

其实就是加入一个插件:

<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<!-- 在控制台打印执行日志 -->
<verbose>true</verbose>
<!-- 重复生成时会覆盖之前的文件-->
<overwrite>true</overwrite>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

数据库驱动请对应修改。

至于Gradle版请看Kotlin版源码。

6.2 配置文件

这里是参考别人的配置文件,修改数据库连接、表名、包名即可:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- context 是逆向工程的主要配置信息 -->
<!-- id:起个名字 -->
<!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 -->
<context id="default" targetRuntime="MyBatis3">
<!--optional,指在创建class时,对注释进行控制-->
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--jdbc的数据库连接 wg_insert 为数据库名字-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="test" password="test" />
<!--非必须,类型处理器,在数据库类型和java类型之间的转换控制-->
<javaTypeResolver>
<!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal 类 -->
<!-- 不是 double 和 long 类型 -->
<!-- 使用常用的基本类型代替 sql 包下的引用类型 -->
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- targetPackage:生成的实体类所在的包 -->
<!-- targetProject:生成的实体类所在的硬盘位置 -->
<javaModelGenerator targetPackage="pers.entity"
targetProject="src/main/java">
<!-- 是否允许子包 -->
<property name="enableSubPackages" value="false"/>
<!-- 是否对modal添加构造函数 -->
<property name="constructorBased" value="true"/>
<!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
<property name="trimStrings" value="true"/>
<!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
<property name="immutable" value="false"/>
</javaModelGenerator>
<!-- targetPackage 和 targetProject:生成的 mapper 文件的包和位置 -->
<sqlMapGenerator targetPackage="mapper"
targetProject="src/main/resources">
<!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="pers.dao" targetProject="src/main/java">
</javaClientGenerator>
<!-- tableName是数据库中的表名,domainObjectName是生成的JAVA模型名,后面的参数不用改,要生成更多的表就在下面继续加table标签 -->
<table tableName="user" domainObjectName="User"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false" />
</context>
</generatorConfiguration>

6.3 生成代码

双击生成即可:

生成了实体类、dao接口以及mapper文件。

7 参考源码

Java版:

Kotlin版:

8 参考链接

Spring学习笔记(六):MyBatis集成的更多相关文章

  1. Spring Boot学习笔记(六)mybatis配置多数据源

    application.properties #数据库配置 #数据源类型 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # ...

  2. Spring学习(六)——集成memcached客户端

    memcached是高性能的分布式内存缓存服务器.许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示. 但随着数据量的增大.访问的集中,就会出现RDBMS的负担加重.数据 ...

  3. Spring学习笔记六:Spring整合Hibernate

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6785323.html  前言:整合概述 Spring整合Hibernate主要是把Hibernate中常用的S ...

  4. Spring Boot笔记(六) springboot 集成 timer 定时任务

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.创建具体要执行的任务类: package com.example.poiutis.timer; im ...

  5. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  6. Spring学习笔记(六)—— SSH整合

    一.整合原理 二.整合步骤 2.1 导包 [hibernate] hibernate/lib/required hibernate/lib/jpa 数据库驱动 [struts2] struts-bla ...

  7. Spring学习笔记(一)

    Spring学习笔记(一) 这是一个沉淀的过程,大概第一次接触Spring是在去年的这个时候,当初在实训,初次接触Java web,直接学习SSM框架(当是Servlet都没有学),于是,养成了一个很 ...

  8. spring学习笔记(一) Spring概述

    博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书.  强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...

  9. Spring学习笔记2——表单数据验证、文件上传

    在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...

  10. 不错的Spring学习笔记(转)

    Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是s ...

随机推荐

  1. [转]hpp.h与.h的区别

    原文网址:https://blog.csdn.net/liuzhanchen1987/article/details/7270005 hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实 ...

  2. Simple: SQLite3 中文结巴分词插件

    一年前开发 simple 分词器,实现了微信在两篇文章中描述的,基于 SQLite 支持中文和拼音的搜索方案.具体背景参见这篇文章.项目发布后受到了一些朋友的关注,后续也发布了一些改进,提升了项目易用 ...

  3. Java volatile 关键字底层实现原理解析

    本文转载自Java volatile 关键字底层实现原理解析 导语 在Java多线程并发编程中,volatile关键词扮演着重要角色,它是轻量级的synchronized,在多处理器开发中保证了共享变 ...

  4. Vue学习笔记-jsonl转换显示工具JsonView安装及使用

    一  使用环境: windows 7 64位操作系统 二  jsonl转换显示工具JsonView安装及使用 1.下载: https://github.com/gildas-lormeau/JSONV ...

  5. 行业动态 | 通过使用Apache Cassandra实现实时供应链管理

    借助基于Apache Cassandra的DataStax Enterprise,C&S Wholesale确实得到了他们所需要的东西--一个持续在线的仓库运作整体视图.   视图中包含了原本 ...

  6. C++共享数据保护机制

    下面随笔说明C++共享数据保护机制. 共享数据的保护 对于既需要共享.又需要防止改变的数据应该声明为常类型(用const进行修饰). 对于不改变对象状态的成员函数应该声明为常函数. (1)常类型 ①常 ...

  7. PAT-1167(Cartesian Tree)根据中序遍历序列重建最小堆

    Cartesian Tree PAT-1167 一开始我使用数组进行存储,但是这样可能会导致无法开足够大的数组,因为树如果是链表状的则无法开这么大的数组(虽然结点很少). 正确的解法还是需要建树,使用 ...

  8. Java 常见对象 01

    常见对象·Object类 Object类的概述 * A:Object 类概述 * 类层次结构的根类 * 所有类都直接或间接地继承自该类 * B:构造方法 * public Object() * 回想为 ...

  9. 【pytest官方文档】解读fixtures - 7. Teardown处理,yield和addfinalizer

    当我们运行测试函数时,我们希望确保测试函数在运行结束后,可以自己清理掉对环境的影响. 这样的话,它们就不会干扰任何其他的测试函数,更不会日积月累的留下越来越多的测试数据. 用过unittest的朋友相 ...

  10. Debezium实现多数据源迁移(一)

    背景: 某公司有三个数据库,分别为MySql.Oracle和PostgreSql.原有业务的数据都是来自于这三个DB,此处委托将原有的三个数据库整合成一个Mysql. 要求: 1.不影响原有系统的继续 ...