MyBatis 是什么?

MyBatis 是什么?

一、简介

MyBatis 是一款一流的支持自定义 SQL、存储过程和高级映射的持久化框架。MyBatis 几乎消除了所有的 JDBC 代码,也基本不需要手工去设置参数和获取检索结果。MyBatis 能够使用简单的 XML 格式或者注解进行来配置,能够映射基本数据元素、Map 接口和 POJOs(普通 java 对象)到数据库中的记录。

所有的 MyBatis 应用都以 SqlSessionFactory 实例为中心。SqlSessionFactory 实例通过 SqlSessionFactoryBuilder 来获得,SqlSessionFactoryBuilder 能够从 XML 配置文件或者通过自定义编写的配置类(Configuration class),来创建一个 SqlSessionFactory 实例。

二、从 XML 中创建 SqlSessionFactory 实例

从 XML 中创建 SqlSessionFactory 实例非常简单。建议您使用类资源路径(classpath resource)来加载配置文件,但是您也能够使用任何方式,包括文本文件路径或者以 file:// 开头URL的方式。MyBatis 包括一个叫做 Resources 的工具类(utility class),其中包含了一系列方法,使之能简单地从 classpath 或其它地方加载配置文件。

String resource = "org/mybatis/example/Configuration.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);

XML 配置文件包含 MyBatis 框架的核心设置,包括获取数据库连接的 DataSource 实例,和包括决定事务作用域范围和控制的事务管理等。在这里我们先展示一个简单的例子。

<?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>
         <!-- BlogMapper.xml位于org.mybatis.example这个包下,所以resource写成org/mybatis/example/BlogMapper.xml-->
         <mapper resource="org/mybatis/example/BlogMapper.xml"/>
     </mappers>
 </configuration>

虽然 XML 配置文件中还有很多其它的配置细节,但是,上面的示例显示了最重要的部分。注意 XML 配置文件的头部,会使用 DTD 验证文档来验证该 XML 配置文件。body 部分的 environment 元素,包含了事务管理和连接池配置。Mappers 元素指定了映射配置文件——包含SQL语句和映射定义的 XML 文件。

三、不使用 XML 来创建 SqlSessionFactory

如果您喜欢直接通过 java 代码而不是通过 XML 创建配置选项,或者想创建您自己的配置生成器。Mybatis 提供了一个完整的配置类(Configuration class)它提供了与 XML 文件相同的配置选项。

TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource)
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSesslonFactory = new SqlSessionFactoryBuilder().build(configuration);

请注意,这种方式下的配置添加一个映射类(mapper class)。映射类是包含 SQL 映射注解的 Java 类,从而避了使用 XML。但是,由于注解的一些局限性以及 MyBatis 映射的复杂性,XML仍然是一些高级的映射功能(如嵌套连接映射,NestedJoinMapping)所必须的方式。基于这个原因,如果存在 XML 文件,MyBatis 自动寻找并加载这个XML文仵。在这种情况下,BlogMapper.xml 将会被类路径下名称为 BlogMapper.class 的类加载。

四、从 SqlSessionFactory 获取 SqlSession

现在您已经创建了一个 SqlSessionFactory(指上的 sqlMapper),正如它名字喑示那样,您可以通过它来创建一个 SqlSession 实例。SqlSession 包含了所有执行数据厍 SQL 语句的方法。您能够直接地通过 SqlSession 实例执行映射 SQL 语句。例如:

SqlSession session = sqlMapper.openSession();
try {
    Blog blog= (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
    session.close();
}  

虽然这种方法很有效,MyBatis 以前版本的用户对此也可能很熟悉,但现在有一个更简便的方式,那就是对给定的映射语句,使用一个正确描述参数与返回值的接囗(如BlogMapper.class),您就能更清晰地执行类型安全的代码,从而避免错误和异常。如:

SqlSession session = sqlMapper.openSession();
try {
    BlogMapper mapper = session.getMapper(BlogMapper.class)
    Blog blog = mapper.selectBlog(101);
} finally {
    session.close();
}  

现在,让我们一起探索它们究竟是如何执行的。

五、探索映射SQL语句

此时,您可能想知道 SqlSession 或者映射器类(Mapper class)是怎样执行的。映射 SQL 语句是一个很大的主题,该主题将可能占据本文档的大部分内容。但是,为了让您看到它是怎样运行的,这里举两个例子。

在上面的例了中,映射语句已经在 XML 配置文件或注解中定义。让我们首先来看看 XML 配置文件,所有 MyBatis 提供的功能特性都可以通过基于 XML 映射配置文件配置来实现。如果您以前使用过出 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" parameterType="int" resultMap="Blog">
        select * from Blog where id=#{id}
  </select>
</mapper>

这个简单的例子看起来有不少的开销,但它确实非常地轻巧,只要您喜欢,您可以在一个映射 XML 文件中定义许多映射语句。虽然会有一些 XML 头部和 DOCTYPE 声明,但该文件余下的部分是自解(self explanatory,可理解为不加解释就能明自)的。它定义了映射语句名称 "selectBlog",在命名空间 "org.mybatis.example.BlogMapper",允许您通过指定完整类名 "org.mybatis.example.BlogMapper" 来访问上面的例子:

Blog blog= (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);

这非常类似 java 中通过完整类名来调用方法,而这样做是有原因的。这个名称可以直接映射到一个具有相同命名空间的映射类,这个映射类有一个方法的名称、参数及返回类型都与 select 映射语句相匹配。正如您前面看到的,这使您很简单地调用映射类里的方法。

对映射类还有一个更好的方法,就像前的 BlogMapper。它们的映射语句不需要完全在 XML 中配置。相反,它们可以使用 Java 注解。例如上面的 XML 配置可以替換为:

package org.mybatis.example;
public interface BlogMapper{
    @Select("select * from Blog where id=#{id}")
    Blog selectBlog(int id);
}

下面是另外的一个例子:

BlogMapper mapper = session.getMapper(BlogMapper.class)
Blog blog = mapper.selectBlog(101);

第二种方法有很多好处。第一,它不依赖于字符串,所以更安全。第二,如果您的IDE有自动完成功能,您可以利用这功能很快导航到您的映射 SQL 语句。第三,您不需要关注返回类型,不需要进行强制转换,因为使用接口已经限定了返回类型,它会安全地返回。

对简单的映射语句,使用注解可以显得非常地清晰。但是 java 注解本身的局限难于应付更复杂的语句。如果您准备要做某些复杂的事情,最好使用 XML 文件来配置映射语句。

这将由您和您的项目小组来确定哪种方式是适合的,以一致的方式来定义映射语句是非常重要的。也就是说,您不会被限于仅用一种方式。您能够非常容易地从基于注解的映射语句移植到 XML 配置文件中,反之亦然。

六、关于命名空间

1、命名空间:在以前的版本中是可选的、复杂的且没多大用处。但在这个版本中,命名空间是必须的,并且不仅仅是简单地使用完整类名来隔离区分语句。

如您看到的那样,命名空间能够进行接口绑定,即使您认为现在不会使用到它,但您应该按照这些准则来做。一旦使用了命名空间并且放入适当的 Java 包命名空间中将会使您的代码清晰,并提高 MyBatis 的长期可用性。

2、名称解析:为了减少大量地输入,MyBatis 对所有的配置元素,包括 statements、resultmaps、caches 等使用下面的名称解析规则:

  • 完整类名:(例如:"com.mypackage.MyMapper.selectAllThings")可用来直接查找并使用。
  • 短名称:(例如:"selectAllThings")可用来引用明确的实体对象。但是,如果出现有两个或更多(例如"com.foo.selectAllThings和com.bar.selectAllThings")实体对象,您将收到一个错误报告(短名称含糊不清),因此,这时就必须使用完整类名。