前言:本人所写的文章仅作为自己的自学记录,并不是教程,我也是自己摸索,自己学习,所以写的文章可能会存在问题,有些文章也参考别人的或者是官方文档的,用来加深自己的理解,还望前辈指教,谢谢!
MyBatis是支持定制化sql、存储过程以及高级映射的优秀的优秀的持久层框架。MyBatis几乎避免了所有的jdbc代码和手动设置参数以及获取结果集。MyBatis可以对配置和原生Map使用简单的XML或者注解,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
使用的时候,主要包括以下几个步骤
org.mybatis
mybatis
x.x.x
每个基于mybatis的应用都是以一个SqlSessionFactory的实例为中心的。SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。而SqlSessionFactoryBuilder则可以从mybatis的xml配置文件中或者一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。即可以通过xml配置文件的方式或者Java代码直接构建的方式来获取SqlSessionFactory实例。
从xml文件中构建SqlSessionFactory的实例非常简单,建议使用类路径下的资源文件进行配置,也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者file://的URL形式的文件路径来配置。mybatis包含一个名叫Resources的工具类,它包含一些实用的方法,可使从classpath或者其他位置加载资源文件更加容易。
xml配置文件(configuration xml)中包含了对mybatis系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务范围和控制方式的事务管理器(TransactionManager)。xml配置文件的详细内容后面再探讨。
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
还有一种办法是直接通过Java代码来构建SqlSessionFactory,不建议使用,若想试一下,可以查看官方API
首先,先编写一个简单的sql映射文件,以后还要对sql映射文件进行详细的学习使用。
在第二步中已经获取到了sqlSessionFactory,顾名思义,就可以从sqlSessionFactory中获取SqlSession实例了。SqlSession完全包含了面向数据库执行sql命令所需的所有方法。
调用并执行sql语句有两种办法,一种是直接通过SqlSession调用,一种是通过开发的mapper接口来调用。
1)直接通过SqlSession调用
SqlSession session = sqlSessionFactory.openSession();
try {
Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
session.close();
}
2)通过开发的mapper接口调用
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
} finally {
session.close();
}
mapper接口开发的方式有很多优势,首先它不是基于字符串常量的,就会更安全;其次,如果你的IDE有代码补全的功能,那么可以在有了已映射sql语句的基础之上利用这个功能。
对于BlogMapper这样的映射类(Mapper.class)来说,还有一招,就是它们的sql映射语句不需要用xml来做,取而代之的是直接使用Java的注解。比如上面xml示例通过mapper接口开发时,原本的mapper接口为:
package org.mybatis.example;
public interface BlogMapper {
Blog selectBlog(int id);
}
当不需要xml来做的时候,直接使用Java注解的时,mapper接口就如下,不需要再编写xml映射文件
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
可以发现在接口 Blog selectBlog(int id); 上面多了@Select("SELECT * FROM blog WHERE id = #{id}") 这个注解,对于简单的sql语句来说,使用注解可以使代码显得更加简洁,但是Java注解对于稍微复杂的sql语句就会显得力不从心并且更加混乱。因此当需要做复杂的事情时,最好还是xml映射文件的方式。
命名空间在早期的版本是可选的,但是现在的命名空间是必须的,目的是希望能比只是简单的使用更长的完全限定名来区分sql语句更进一步。
为了减少输入量,mybatis对所有的命名配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
依赖注入框架可以创建线程安全的、基于事务的SqlSession和映射器(mapper)并直接将它们注入到bean中,交给容器来管理,因此可以直接忽略它们的生命周期。比如spring框架。
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory,就不再需要它了。因此SqlSessionFactoryBuilder实例的最佳范围是方法范围(也就是局部范围变量)。可以重用SqlSessionFactoryBuilder来创建多个SqlSessionFactory实例,但是最好还是不要让其一直存在以足以保证所有的xml解析资源开放给跟重要的事情。
SqlSessionFactory
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它们进行清除或者重建。使用SqlSessionFactory的最佳实践是在应用的运行期间不要重复创建多次,多次重复创建SqlSessionFactory被视为代码“坏味道(bad smell)”。因此 SqlSessionFactory的最佳范围是应用范围。有很多方法可以做到,最简单的方法就是使用单例模式或者静态单例模式。
SqlSession
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不是线程安全的,因此是不能被共享的,所以它最佳的范围是请求或者方法范围。绝对不能将SqlSession实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将SqlSession实例的引用放在任何类型的管理范围中,比如Servlet架构中的HttpSession。如果正在使用一种web框架(比如SpringMVC),要考虑SqlSession放在一个和HTTP请求对象相似的范围中。换句话说,每次收到HTTP请求,就可以打开一个SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,应该把这个关闭操作放在finally块中以确保每次都能执行关闭。下面的示例就是一个确保SqlSession关闭的标准模式
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
映射器实例(Mapper Interfaces)
映射器实例(即 Mapper Interfaces)是创建用来绑定映射sql语句的接口。映射器接口的实例是从SqlSession中获得的。因此从技术层面讲,映射器实例的最大范围是和SqlSession相同的,,因此它们都是从SqlSession里被请求的。映射器的最佳范围是方法范围,也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可废弃。并不需要显示地关闭映射器实例,尽管在整个请求范围(request scope)保持映射器实例也不会有什么问题,但是很快就会发现,像SqlSession一样,在这个范围上管理太多的资源的话会难于控制。所以要保持简单,最好把映射器放在方法范围(method scope)内。示例如下:
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
}