原创内容,转载请注明出处
介绍
什么是Mybatis?
Mybatis是一个优秀的持久化框架,支持自定义Sql,存储过程和高级映射。Mybatis消除了几乎所有的Jdbc代码和手工设置参数和返回的结果集。Mybatis可以对配置和原生Map使用简单的Xml或者注解,将接口和Java Pojo对象映射成数据库的记录。
帮助建立更好的文档
如果你发现这个文档任何地方的缺陷,或者缺少重要功能的文档,那么最好的方法是去学习它,并且自己去把它编写在文档上。
这个xdoc格式的文档的来源是在Git项目中,检出这版本库,更新他们并且发送一个pull request。
你是这个文档最好的作者,像你这样的人必须读它。
翻译
用户能够读取Mybatis以下翻译版本英语、日语、中文。
你想读自己母语版的Mybatis吗?那就提供你们母语的文档给我们吧。
新手入门
安装
使用Mybatis,你只需要在你的的类路径里包含mybatis-x.x.x.jar文件。
如果你是使用Maven,那么你只需要添加一下依赖在你的pom.xml文件中。
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>x.x.x</version> </dependency>
用Xml文件创建SqlSessionFactory
每个Mybatis应用程序都是以SqlSessionFactory实例为中心。一个SqlSessionFactory实例能够从SqlSessionFactoryBuilder类获得。SqlSessionFactoryBuilder可以从一个Xml文件或自定义的Configuration类的实例建立一个SqlSessionFactory实例。
从一个Xml文件去创建SqlSessionFactory实例是非常简单的,推荐你使用一个类路径资源去配置。但是你也可以使用InputStream实例,包含了一个字符文件路径或者fill://URL形式的路径。Mybatis有一个Resources的工具类,它包含一系列方法,使得从类路径或这其他位置加载资源变得更加简单。
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
这个Xml配置文件包含了Mybatis系统的核心配置,包含了获取数据库连接(Connection)实例的数据源(DataSource)和决定事务范围和控制类(TransactionManager)。完整详细的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="${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>
当然还有很多可以在这xml文件配置,上面的例子指出了重要的配置部分。大家留意下xml文件的头,被用来校验xml文档使用。environment元素体包含事务管理和连接池的环境配置。mappers元素体包含了一系列mapper,这些mapper包含了xml文件或者其他Java接口类,它们包含了sql代码和映射定义。
不使用xml文件创建SqlSessionFactory
如果你宁愿直接使用Java代码,而不使用xml文件创建配置,或者创建你自己的配置构建器。Mybatis提供了一个完整的Configuration类,它提供了和xml文件相同的配置选项。
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类是一个java类,它包含了sql映射注解,避免了使用xml文件配置。然而,由于Java注解的一些限制和一些复杂的Mybatis映射,对于一些高级映射(比如嵌套连接映射)xml映射依然是需要的。由于这个原因,Mybatis将自动查找和导入相同名字的xml文件的存在(在这个例子里,BlogMapper.xml文件将会被加载基于类路径和BlogMapper.class名称)。具体详细将在后面讲到。
从SqlSessionFactory获取SqlSession
现在你已经有了SqlSessionFactory实例,从它的名称上来看,你将可以从它那里获取SqlSession实例。SqlSession完全包含了数据库需要执行的sql命令的任何方法。你可以通过SqlSession直接执行已经映射的sql语句。如下例子
SqlSession session = sqlSessionFactory.openSession();
try {
Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
session.close();
}
虽然按这种方法处理,并且对于使用老版本Mybatis的用户来说,有一种更清晰的感觉。使用对于给定语句就可以正确描述参数和返回值的接口(例如BlogMapper.class),你将能执行清晰和类型安全的代码,没有错误的字符常量。
例子
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
} finally {
session.close();
}
现在让我们一起研究在这里是怎么正确执行的。
探索映射sql语句
到这里你可能会惊讶SqlSession或者Mapper类到底执行了什么。映射sql语句是一个很大的主题,它似乎占了文档的很大一部分。不过为了让你知道是怎么运行的,这里将给出两三个例子。
上面的任意例子,sql语句可以被定义在xml文件或者用注解来表示。让我们先来看看xml文件吧。Mybatis提供了一套基于xml文件的映射语言完整的功能,使得Mybatis流行了好长时间。如果你以前使用过Mybatis,那么你将会更加熟悉这些概念,然而在后来xml文档又有许多改进。这里使用一个基于映射语句的xml文件例子,将会满足上述SqlSession的调用。
<?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>
虽然上面的例子看起来都非常简单,实际上它们是非常轻量级的。在一个mapper xml文件中,你想定义多少个映射语句都是可行的,这样xml头和文档声明就显得并不多。文件的剩余部分就更加明细了。在org.mybatis.example.BlogMapper命名空间下,定义了一个名为selectBlog的映射语句,这样就允许你叫它的完整名称org.mybatis.example.BlogMapper.selectBlog,就像我们下面例子做的一样。
Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
注意这可能和调用一个完整限定名Java类有些类似,这样做是有原因的。这名字可能被直接映射一个在命名空间中相同名字的Mapper类,方法将匹配名字,参数和返回类型在已映射的查询语句中。如上面,能够允许你非常简单的调用Mapper接口类的方法,不过这里我们将再来一个例子。
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
第二个方法将有一些优势。首先它不依赖字符变量,因此它更安全。其次如果你的IDE有代码补全功能,你将可以利用它在你的映射sql语句中。
提示:关于名称空间的提示
命名空间是可选的在旧版本的Mybatis,然而这些都会造成迷惑和无益的。现在的版本命名空间是要求必须的。
命名空间使得你看到的接口绑定,甚至尽管你今天不想这么做,但是你还是需要按规定约束来执行以防哪天你改变你的想法。使用命名空间,并将它放在你的合适的java包中,你的代码将会更加清晰整洁,并提高Mybatis的可用性。
名称解析:为了减少键盘频繁输入,Mybatis使用以下名称解析规则去解析所有的配置元素,包括语句,结果映射,缓存等等。
1.完整的限定名称(例如com.mypackage.MyMapper.selectAll)是可以直接查找和使用的。
2.简单名称(例如selectAll)可以被当作任何明确实体的引用,然而如果有两个或更多个该名称(例如com.foo.selectAll和com.bar.selectAll),那么你将会收到一个错误报告,说简单名称是不清晰,因此必须使用完整限定名称。
有一个或多个Mapper类像BlogMapper,它们的映射语句都不需要映射xml文件,它们将使用java注解,例如,上面的xml文件将被淘汰和替换。
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
注解对于简单的语句来说是更加的简单清晰,然而Java注解对于复杂语句有限制并且会产生混乱。因此如果你需要一些负责的语句,你最好使用xml文件映射。
你的映射语句使用一致的的方法是非常重要的,并且它完全取决于你和你的团队。也就是说你不要局限于一种方法。你可以很简单的将注解的映射语句迁移到xml中。
范围和生命周期
去理解多种范围和生命周期类是非常重要的。使用它们错误可能会产生严重的并发问题。
提示:对象生命周期和依赖注入框架
依赖注入框架可以创建线程安全,事务处理SqlSessions ,直接映射和注入它们到你的bean中,因此你可以忘掉它们的声明周期。你可能需要看Mybatis-Spring 或者Mybatis-Guice子工程去了解更多关于Mybatis和依赖注入框架。
SqlSessionFactoryBuilder
该类会被实例化,使用和丢弃。一旦你创建了你的SqlSessionFactory,它将不需要保留下来。因此最好的范围是实例化SqlSessionFactoryBuilder的方法范围(比如一个本地方法变量)。你可以重复使用SqlSessionFactoryBuilder去建立多个SqlSessionFactory实例,但是最好是不需要保留下来,以确保所有的xml文件解析资源被释放并教给其他重要的事情。
SqlSessionFactory
一旦被创建,SqlSessionFactory就应该在你的应用程序执行期间存在。没有理由去清理或重建它。在一个应用程序运行期间不重建SqlSessionFactory多次是最好的做法。SqlSessionFactory的最好范围是应用程序范围。它可以从很多通过很多中方式来获得,最简单的是使用单例模式或者静态单例模式。
SqlSession
每个线程应该有他自己的SqlSession实例。SqlSession是不需要共享的并且是线程不安全的,因此最好的范围是请求范围或者方法范围。SqlSession实例的引用不能是一个静态的字段或者一个类的实例字段,SqlSession实例的引用不能放在任何管理范围中,像Servlet框架的HttpSession类。如果你是用一个web框架,应该考虑SqlSession在Http请求的相似范围中。换句话说,在接收一个Http请求,你可以打开一个SqlSession,然后返回一个响应,接着你将关掉SqlSession。关闭SqlSession是非常重要的,你应该一直确保它被关闭在finally代码块中。以下是确保SqlSession关闭的标准模式。
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
在你的整个代码中
使用一致的模式将能确保所有数据库资源被正确的关闭。
Mapper实例
Mappers是你创建去和你的映射语句绑定的接口类。mapper解耦的实例化是从SqlSession类获取。从技术上来看,任何mapper实例的最大范围是和SqlSession一样,因为他们都是都是被请求的。但是mapper实例最好的范围是方法范围,它们应该在被调用的方法中被请求,然后资源回收,他们不需要明确的去关闭。保持简单,最好包mapper放在方法范围,以下例子示范展示了这个实践。
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
}
突然发现官方已经有了中文文档,故而停止翻译