Mybatis的原理介绍及超详细使用
作者:鱼仔
博客首页: https://codeease.top
公众号:Java鱼仔
# (一)MyBatis简单介绍:
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects。
简而言之,MyBatis是一个能将传统JDBC变得很方便和易于维护的框架。我们只需要提供SQL语句,而建立连接,创建Statement,处理JDBC异常等工作都可以交给MyBatis去做。
mybatis官方中文网站:https://mybatis.org/mybatis-3/zh/index.html
学习技术还是强烈建议大家通过官网学习,并参考博客,形成自己的一份见解。本系列文章基于Mybatis官方文档编写。
# (二)MyBatis环境搭建:
在这里我们使用maven仓库来引入对应的依赖,我们选一个用的最多的maven仓库
maven仓库:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
2
3
4
5
6
# 2.1 创建一个数据库用于mybatis的学习
create database `mybatis`;
use mybatis;
create table `user`(
`id` INT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(40) DEFAULT NULL,
primary key(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
insert into user(name) values('javayz'),('zhangsan')
2
3
4
5
6
7
8
9
10
这里主要建了一个数据库,并新建一张user表,并往里面插入两条数据,虽然现在数据库的可视化工具很多,还是建议大家平常联系中手动编写sql语句。
# 2.2 新建项目
新建一个maven项目,并导入mybatis的相关依赖,我们需要在pom.xml中导入三个依赖:mysql驱动依赖、mybatis依赖以及junit依赖用于测试。
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2.3 创建mybatis配置文件
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
上面这几句话就是从官方中文文档中获取整合的,MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心,我们需要首先建立一个mybatis的配置文件。官方文档中把配置文件的名称叫做mybatis-config.xml。
我们在resources目录下新建这样一个配置文件mybatis-config.xml
<?xml version="1.0" encoding="UTF8" ?>
<!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.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--每个mapper.xml都需要在mybatis配置文件中进行配置-->
<mappers>
<mapper resource="com/javayz/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这一段代码同样来自于官方文档,配置了事务管理器为JDBC,以及连接需要的一些属性,这些属性改成自己的配置。
最后mappers标签中需要加入接下来在代码中写的mapper.xml路径,不然运行时会报以下错误:
org.apache.ibatis.binding.BindingException: Type interface com.javayz.mapper.UserMapper is not known to the MapperRegistry.
# 2.4 编写工具类
接下来的步骤应该是去获取配置文件并构建SqlSessionFactory,官网提供了这样一段代码:
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2
3
这里我们去编写一个工具类来实现以后需要多次实现的内容。
新建一个utils包,并在utils包下创建MybatisUtils类
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//获取SqlSessionFactory工厂类
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
//通过SqlSessionFactory获取SqlSession实例
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
通过上面的工具类即可获取到sqlSession实例,剩下的就是对sqlSession一系列操作了。
# (三) Mybatis代码实践
首先编写一个实体类User,这一块的代码不作介绍了
public class User {
private int id;
private String name;
//......
//省略构造方法、get、set、toString方法
}
2
3
4
5
6
SqlSession对数据库的操作既可以使用XML方式也可以使用注解的方式,我们这里先介绍XML的方式,还是参考官方中文文档里面的xml代码。
新建一个名称为mapper的包,在里面新建一个UserMapper接口以及UserMapper.xml
public interface UserMapper {
List<User> getUserList();
}
2
3
UserMapper.xml
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javayz.mapper.UserMapper">
<select id="getUserList" resultType="com.javayz.pojo.User">
select * from user;
</select>
</mapper>
2
3
4
5
6
7
8
9
xml文件中有几个点需要提一下,首先是namespace,每一个接口对应一个命名空间,这个命名空间就是接口的全路径。其次还需要注意resultType,也就是返回的类型,如果只填User也无法被找到。
最后在test包下编写测试类
public class UserMapperTest {
@Test
public void test(){
//获取SqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行Sql
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
System.out.println(userList);
sqlSession.close();
}
}
2
3
4
5
6
7
8
9
10
11
12
如果一切顺利这里就会输出正确结果,但是很有可能会出现下面这段报错信息
Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/javayz/mapper/UserMapper.xml
意思是找不到UserMapper.xml这个文件,但我们明明有,这里的问题是maven在编译过程中没有将上面的xml文件导出,我们需要在pom.xml中增加下面一段来配置resources
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
最终输出正确结果。
# (四)作用域和生命周期
在上面编写工具类的时候,我们用到了三个类:SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession。
由于SqlSession不是线程安全的,意味着在并发情况下使用不当会造成很严重的并发问题,因此我们有必要讨论这三个类的作用域以及生命周期。
首先SqlSessionFactoryBuilder是用来创建SqlSessionFactory的,用完之后就可以丢弃,因此将SqlSessionFactoryBuilder放到方法作用域内即可。
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,因此我们将它放到应用作用域,在工具类中我将其设置成一个静态变量,这样就不会多次去创建。
SqlSession 的实例不是线程安全的,SqlSession 只在一个方法或者一个请求中使用,并且使用完之后必须关闭它。参考我上面的UserMapperTest 类,创建SqlSession 以及关闭SqlSession 都在一个方法中完成。
注意如果你使用的是依赖注入框架如MyBatis-Spring,就不必关注生命周期,因为依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器
# (五)总结
整体来看Mybatis的使用好像和jdbc相比没有方便多少,那是因为到现在为止我们做的都是各种配置,而等配置完成后,我们需要做的只不过是在mapper下写各种增删改查罢了。