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. SharedPreferences 数据传输中遇到的一些问题总结

    原构想:MainActivity 设置两个按钮,btn1--跳转Main2Activity通过复选框组选择并提交,btn2--跳转Main3Activity通过RecycleView显示选择结果. 主 ...

  2. javascript 十大经典排序

    首先生成一个数字数组: let arr = Array.from({length:20},x=>{return Math.ceil(Math.random()*10**2)}) console. ...

  3. linux系统导出随笔

    导出时,不要用root用户忽略某张表的命令(多张表则直接往后加即可) --ignore-table=firewall_8088.operate_history --ignore-table=firew ...

  4. SpringCloud之服务网关

    1.zuul 1.1定义 zuul叫路由网关,它包含对请求的路由和过滤的功能. 路由负责将外部的请求转发到具体的微服务实例上,是实现外部访问统一入口的基础.而过滤是负责对请求的处理过程进行干预,是实现 ...

  5. 分分钟钟学会Python - 第四章 文件操作

    4.1 文件基本操作 obj = open('路径',mode='模式',encoding='编码') obj.write() # 写入 obj.read() # 读取 obj.close() #关闭 ...

  6. Lua C++交互 应用实例步骤(UserData使用)

    一.配置Lua C++交互环境 1.下载Lua 包环境 地址: https://www.lua.org/download.html ,我们这里用的是5.4.2版本. 2.新建C++ 控制台应用程序 3 ...

  7. 在ASP.NET Core中用HttpClient(一)——获取数据和内容

    在本文中,我们将学习如何在ASP.NET Core中集成和使用HttpClient.在学习不同HttpClient功能的同时使用Web API的资源.如何从Web API获取数据,以及如何直接使用Ht ...

  8. linux 设置DNS解决,不能ping 域名的问题

    vi /etc/resolv.conf nameserver 114.114.114.114

  9. Java split 根据指定字符串分隔成list数组的用法

    String str="Java string split test";      String[] strarray=str.split(" ");//得到一 ...

  10. WPF 基础 - 图形的效果与滤镜

    UIElement 有 BitmapEffect 和 Effect 属性,BitmapEffect 是由 CPU 的运算能力实现的,比较耗性能,推荐使用 Effect: Effect 包括但不限于 D ...