mybatis基础知识
MyBatis 是一个数据库操作的框架,支持定制 SQL、存储过程和高级映射。消除了几乎所有的 JDBC 代码以及参数设置和结果检索的手动操作。 MyBatis 可以使用简单的 XML 或注解进行配置。并将 原始数据类型、POJO 类映射到数据库记录中
起步
引入依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<!-- 截止写作本文时间,最新版本为 3.5.5 -->
<version>3.5.5</version>
</dependency>
构建SqlSessionFactory
每一个使用mybatis的应用程序中都以 SqlSessionFactory 为中心。可以通过 SqlSessionFactory 获得 SqlSessionFactory 实例。SqlSessionFactoryBuilder 可以从 XML 配置文件或 Configuration 类的自定义准备的实例构建出 SqlSessionFactory。
通过XML构建 SqlSessionFactory
配置文件包含 mybatis 系统核心的配置,包括用于获取数据库连接实例的数据源,以及用于确定事务范围和控制的 TransactionManager。下面是一个简单的示例。更多详细的配置说明可以参考 Configuration配置说明
<?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="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
environment 节点的主题包含用于事务管理和连接池的环境配置。
mappers 节点包含了一系列的 mapper,即 包含SQL 代码和映射定义的 XML 或者 注解标记的 Java 接口类。
通过Java代码构建 SqlSessionFactory
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory =
new JdbcTransactionFactory();
Environment environment =
new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(configuration);
在该例子中,配置添加了一个mapper类,Mapper类是包含避免使用XML的SQL映射注释的Java类。但是,由于Java注释的一些限制和一些MyBatis映射的复杂性,最高级的映射仍然需要XML映射(例如嵌套连接映射)。因此,如果对等XML文件存在,MyBatis将自动查找并加载它(在本例中,将根据类路径和BlogMapper.class的名称加载BlogMapper.xml)。
从SqlSessionFactory获取SqlSession
现在您已经有了一个SqlSessionFactory,顾名思义,您可以获取SqlSession的一个实例。SqlSession包含对数据库执行SQL命令所需的所有方法。可以直接针对SqlSession实例执行映射的SQL语句
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = session.selectOne(
"org.mybatis.example.BlogMapper.selectBlog", 101);
}
虽然通过这种方法可以获取到对应的 mapper,但是由于手动编写了Statement ID(即 org.mybatis.example.BlogMapper.selectBlog)容易写错。因此在新版本中建议使用以下方法
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
}
探索映射的SQL语句
通过XML定义好SQL语句,并绑定到 Java 接口类上。
<?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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
之后,可以通过SqlSession来获取Mapper接口代理对象,来执行SQL语句。
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
注解映射SQL
除了使用XML来定义SQL的映射,也可以通过注解的方式来定义
package org.mybatis.example;
public interface BlogMapper {
// 通过注解 @Select 来定义SQL
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
调用方式和利用XML来定义时一样
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
理解各组件的生命周期
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃。一旦创建了,就不需要保留它。因此SqlSessionFactoryBuilder实例的最佳作用域是方法作用域(即一个本地方法变量)。您可以重用SqlSessionFactoryBuilder来构建多个SqlSessionFactory实例,但是最好不要保留它,以确保释放所有XML解析资源用于更重要的事情。
SqlSessionFactory
一旦创建,SqlSessionFactory应该在应用程序执行期间存在。应该没有什么理由去处理它或者重新创造它。在应用程序运行时,最好不要多次重新构建SqlSessionFactory。这样做应该被认为是一种不好的气味。因此SqlSessionFactory的最佳作用域是应用程序作用域。这可以通过多种方式实现。最简单的是使用单例模式或静态单例模式
SqlSession
每个线程都应该有自己的SqlSession实例。SqlSession的实例不能共享,并且不是线程安全的。因此,最好的作用域是请求或方法作用域。永远不要在静态字段甚至类的实例字段中保存对SqlSession实例的引用。不要将对SqlSession的引用保存在任何类型的托管范围中,比如Servlet框架的HttpSession。如果您正在使用任何类型的web框架,请将SqlSession看作遵循与HTTP请求类似的作用域。换句话说,在接收到HTTP请求后,您可以打开一个SqlSession,然后在响应请求之后关闭它。关闭SqlSession非常重要,应该使用try-finaly的方式来保证其正确关闭。
try (SqlSession session = sqlSessionFactory.openSession()) {
// do work
}
Mapper Instances
映射器是用于绑定到映射语句的接口。mapper接口的实例是从SqlSession获得的。因此,从技术上讲,任何mapper实例的范围都与请求它们的SqlSession相同。然而,mapper实例的最佳作用域是方法作用域。也就是说,应该在使用它们的方法中请求它们,然后丢弃它们。它们不需要显式关闭。虽然在整个请求中都保留它们不是问题,但与SqlSession类似,可能会发现在这个层次上管理太多的资源会很快失去控制。保持简单,将映射器保持在方法范围内
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
}