深入浅出MyBatis技术原理与实战(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-24 16:30:41

点击下载

作者:杨开振

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

深入浅出MyBatis技术原理与实战

深入浅出MyBatis技术原理与实战试读:

前言

随着手机、平板电脑等移动终端的广泛应用,移动互联网时代已经到来。在这个时代里,构建一个高效的平台并提供服务是移动互联网的基础,在众多的网站服务中,使用Java构建网站的不在少数。移动互联网的特点是大数据、高并发,对服务器往往要求分布式、高性能、高灵活等,而传统模式的Java数据库编程框架已经不再适用了。在这样的背景下,一个Java的持久框架MyBatis走入了我们的世界,它以封装少、高性能、可优化、维护简易等优点成为了目前Java移动互联网网站服务的首选持久框架,它特别适合分布式和大数据网络数据库的编程。

本书主要讲解了MyBatis的应用。从目前的情况来看,国内图书市场上没有介绍MyBatis的书籍,有的只是官方的API和少数的几篇博客文章,国外图书市场上的这类书籍也是凤毛麟角,这使得系统学习MyBatis困难重重。官方的API只是简单介绍了MyBatis有些什么功能和一些基本的使用方法,没有告诉我们如何用好,其中原理是什么,需要注意哪些问题,这显然是不够的。有些博客虽然讲解得比较深入,但是内容支离破碎,没有形成一个完整的知识体系,不易于初学者对MyBatis进行系统学习。随着移动互联网应用的兴起,系统掌握MyBatis编程技巧已经成了用Java构建移动互联网网站的必要条件。为了顺应时代的要求,笔者写下了这本书,以期为广大需要掌握MyBatis的开发者提供学习和参考的资料。

阅读本书要求开发人员拥有Java语言基础和JDBC基础知识,对数据库也要掌握入门知识,最好能够掌握常用的设计模式,因为在介绍MyBatis构造时,常常涉及设计模式,尤其是第6章和第7章的内容。

本书以讲解MyBatis基础运用和原理为主,所以适合初级到中高级开发人员阅读。

本书分为三大部分。

第一部分是MyBatis基础应用,主要介绍如何高效地使用MyBatis。

第1章:MyBatis的内容简介,告诉读者MyBatis是什么,在何种场景下使用它。

第2章:主要介绍MyBatis的基础模块及其生命周期,并给出实例。

第3章:主要介绍MyBatis配置的主要含义和内容。

第4章:介绍MyBatis映射器的主要元素及其使用方法。

第5章:介绍动态SQL,助你轻松应对大部分的SQL场景。

第二部分是MyBatis原理,我们将深入源码去理解MyBatis的内部运行原理以及插件的开发方法和技巧。

第6章:介绍MyBatis的解析和运行原理,我们将了解到SqlSession的构建方法,以及其四大对象是如何工作的。

第7章:在第6章的基础上着重介绍MyBatis的插件,这里我们将学习插件的设计原理,以及开发方法和注意的要点。

第三部分是MyBatis的实战应用,主要讲解MyBatis的一些实用的场景。

第8章:介绍MyBatis-Spring,主要讲解如何在Spring项目中集成MyBatis应用,帮助读者在Spring的环境中顺利使用MyBatis。

第9章:介绍MyBatis的实用场景,精选一批典型且又常用的场景。详细解析每一个场景下,开发人员需要注意避免的一些错误和性能上的损失。

MyBatis源于2002年的iBatis项目,至今MyBatis中依然有许多iBatis的痕迹。本书默认使用MyBatis的版本是3.3.0,使用MyBatis-Spring的版本是1.2.3。而历史上的iBatis的书籍已经跟不上技术发展的步伐,于是笔者通过自己的努力和实践,在研究MyBatis源码的基础上,写作本书。从本书中既能学习如何使用MyBatis,也可以学习MyBatis的原理和应用,为国内的MyBatis开发者提供一条系统掌握MyBatis编程技巧的捷径,当然读者也可以把本书作为工具书参考。在实际操作中,MyBatis往往是结合Spring使用的,于是本书花费了一些篇幅讲解MyBatis-Spring技术,笔者也会略略提到Spring项目的内容,以便更好地论述它们。最后笔者还将讲解一些使用频率高、参考价值大的场景,使读者能熟练掌握MyBatis的开发。

本书坚持实用原则,对于一些使用频率低的技术并没有提及太多,比如注解SQL、SQL构造器等内容,使用这些内容,会造成代码的可读性下降。

感谢我的公司为我提供真实的使用MyBatis的环境,所有的程序代码都经过了调试。感谢我的姐姐杨坚,她参与编写并通篇审校了本书,润色了那些晦涩的句子。同时也感谢电子工业出版社的编辑们,尤其是汪达文的全程跟进。没有他们的辛苦付出,就没有本书的成功出版。在出版本书的欣喜之余,也伴着战战兢兢,因为笔者才疏学浅,很多东西都是从对源码的理解和实际操作中获得的,因此书中难免有疏漏之处,或有不能让读者满意的地方。如果有困惑,读者可以发邮件到我的邮箱:ykzhen2013@163.com,也可以在我的博客(http://blog.csdn.net/ykzhen2015)中和我讨论,还望各位同行不吝赐教。杨开振2016年7月第1章MyBatis简介

本章主要介绍了Java ORM的来源和历史,同时分别介绍了JDBC、Hibernate和MyBatis三种访问数据库的方法,在分析它们优缺点的基础上,比较它们之间的区别和适用的场景。1.1 传统的JDBC编程

Java程序都是通过JDBC(Java Data Base Connectivity)连接数据库的,这样我们就可以通过SQL对数据库编程。JDBC是由SUN公司(SUN公司后被Oracle公司收购)提出的一系列规范,但是它只定义了接口规范,而具体的实现是交由各个数据库厂商去实现的,因为每个数据库都有其特殊性,这些是Java规范没有办法确定的,所以JDBC就是一种典型的桥接模式。

传统的JDBC编程的使用给我们带来了连接数据库的功能,但是也引发了巨大的问题。代码清单1-1是用JDBC编程的一个例子。我们将从MySQL数据库中查询一个角色的名称,假设我们已经知道角色编号为1。代码清单1-1:JdbcExample.javapublic class JdbcExample { private Connection getConnection() { Connection connection = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/mybatis?zeroDateTime Behavior=convertToNull"; String user = "root"; String password = "learn"; connection = DriverManager.getConnection(url, user, password); } catch (ClassNotFoundException | SQLException ex) { Logger.getLogger(JdbcExample.class.getName()).log(Level.SEVERE, null, ex); return null; } return connection; } public Role getRole(Long id) { Connection connection = getConnection(); PreparedStatement ps = null; ResultSet rs = null; try { ps = connection.prepareStatement("select id, role_name, note from t_role where id = ?"); ps.setLong(1, id); rs = ps.executeQuery(); while(rs.next()) { Long roleId = rs.getLong("id"); String userName = rs.getString("role_name"); String note = rs.getString("note"); Role role = new Role(); role.setId(id); role.setRoleName(userName); role.setNote(note); return role; } } catch (SQLException ex) { Logger.getLogger(JdbcExample.class.getName()).log(Level.SEVERE, null, ex); } finally { this.close(rs, ps, connection); } return null; } private void close(ResultSet rs, Statement stmt, Connection connection) { try { if (rs != null && !rs.isClosed()) { rs.close(); } } catch (SQLException ex) { Logger.getLogger(JdbcExample.class.getName()).log(Level.SEVERE, null, ex); } try { if (stmt != null && !stmt.isClosed()) { stmt.close(); } } catch (SQLException ex) { Logger.getLogger(JdbcExample.class.getName()).log(Level.SEVERE, null, ex); } try { if (connection != null && !connection.isClosed()) { connection.close(); } } catch (SQLException ex) { Logger.getLogger(JdbcExample.class.getName()).log(Level.SEVERE, null, ex); } } public static void main(String[] args) { JdbcExample example = new JdbcExample(); Role role = example.getRole(1L); System.err.println("role_name => " + role.getRoleName()); }}

从代码中我们可以看出整个过程大致分为以下几步:● 使用JDBC编程需要连接数据库,注册驱动和数据库信息。● 操作Connection,打开Statement对象。● 通过Statement执行SQL,返回结果到ResultSet对象。● 使用ResultSet读取数据,然后通过代码转化为具体的POJO对象。● 关闭数据库相关资源。

使用传统的JDBC方式存在一些弊端。其一,工作量相对较大。我们需要先连接,然后处理JDBC底层事务,处理数据类型。我们还需要操作Connection对象、Statement对象和ResultSet对象去拿到数据,并准确关闭它们。其二,我们要对JDBC编程可能产生的异常进行捕捉处理并正确关闭资源。对于一个简单的SQL在JDBC中尚且如此复杂,何况是更为复杂的应用呢?很快这种模式就被一些新的方法取代,于是ORM模型就出现了。不过所有的ORM模型都是基于JDBC进行封装的,不同的ORM模型对JDBC封装的强度是不一样的。1.2 ORM模型

由于JDBC存在的缺陷,在实际工作中我们很少使用JDBC进行编程,于是提出了对象关系映射(Object Relational Mapping,简称ORM,或者O/RM,或者O/R mapping)。那什么是ORM模型呢?

简单地说,ORM模型就是数据库的表和简单Java对象(Plain Ordinary Java Object,简称POJO)的映射关系模型,它主要解决数据库数据和POJO对象的相互映射。我们通过这层映射关系就可以简单迅速地把数据库表的数据转化为POJO,以便程序员更加容易理解和应用Java程序,如图1-1所示。图1-1 ORM映射模型

有了ORM模型,在大部分情况下,程序员只需要了解Java应用而无需对数据库相关知识深入了解,便可以写出通俗易懂的程序。此外,ORM模型提供了统一的规则使得数据库的数据通过配置便可轻易映射到POJO上。1.3 Hibernate

最初SUN公司推出了Java EE服务器端组件模型(EJB),但是由于EJB配置复杂,且适用范围较小,于是很快就被淘汰了。与EJB的失败伴随而来的是另外一个框架的应运而生。它就是从诞生至今都十分流行的Hibernate。

Hibernate一问世就成了Java世界首选的ORM模型,它是建立在POJO和数据库表模型的直接映射关系上的。

Hibernate是建立在若干POJO通过XML映射文件(或注解)提供的规则映射到数据库表上的。换句话说,我们可以通过POJO直接操作数据库的数据。它提供的是一种全表映射的模型。如图1-2所示是Hibernate模型的开发过程。相对而言,Hibernate对JDBC的封装程度还是比较高的,我们已经不需要编写SQL语言(Structured Query Language),只要使用HQL语言(Hibernate Query Langurage)就可以了。图1-2 Hibernate模型的开发过程

首先我们需要提供hbm.xml文件,制定映射规则。下面以开发角色类为例进行讲解,如代码清单1-2所示。代码清单1-2:TRole.hbm.xml

这是一个简单的XML文件,它描述的是POJO和数据库表的映射关系。Hibernate通过配置文件(或注解)就可以把数据库的数据直接映射到POJO上,我们可以通过操作POJO去操作数据库记录。对于不擅长SQL的程序员来说,这是莫大的惊喜,因为通过Hibernate你几乎不需要编写SQL就能操作数据库的记录。代码清单1-3是Hibernate的配置信息。代码清单1-3:hibernate.cfg.xml org.hibernate.dialect.MySQLDialect com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mybatis?zeroDateTimeBehavior=convertToNull root learn

别看代码很多,但是全局就是这样的一个XML文件,作为数据库连接信息,配置信息也相对简易。然后建立Hibernate的工厂对象(SessionFactory),用它来做全局对象,产生Session接口,就可以操作数据库了,如代码清单1-4所示。代码清单1-4:HibernateUtilpublic class HibernateUtil { private static final SessionFactory sessionFactory; static { try { Configuration cfg = new Configuration().configure ("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; }}

上面的操作为的是产生Hibernate的SessionFactroy。它作为全局,可以到处引用,那么剩下来的使用就非常简单了。比如我们可以用它来实现代码清单1-1的功能,如代码清单1-5所示。代码清单1-5:HibernateExample.javapublic class HibernateExample { public static void main(String[] args) { Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); TRole role = (TRole)session.get(TRole.class, 1L); System.err.println("role_name = >" + role.getRoleName()); } finally { if (session != null) { session.close(); } } }}

按照代码清单1-5的方法来实现代码清单1-1的功能有以下好处:● 消除了代码的映射规则,它全部被分离到了XML或者注解里面去

配置。● 无需再管理数据库连接,它也配置在XML里面。● 一个会话中,不要操作多个对象,只要操作Session对象即可。● 关闭资源只需要关闭一个Session便可。

这就是Hibernate的优势,在配置了映射文件和数据库连接文件后,Hibernate就可以通过Session操作,非常容易,消除了JDBC带来的大量代码,大大提高了编程的简易性和可读性。此外,它还提供级联、缓存、映射、一对多等功能,以便我们使用。正因为具有这些优势,Hibernate成为了时代的主流框架,被大量应用在各种Java数据库的访问中。Hibernate是全表映射,你可以通过HQL去操作POJO进而操作数据库的数据。

但是Hibernate有缺陷吗?当然有,世界上没有完美无缺的方案。作为全表映射框架,举个例子来说,如果我们有张账务表(按年分表),比如2015年表命名为bill2015,到了2016年表命名为bill2016,要动态加映射关系,Hibernate需要破坏底层封装才能做到。又比如说,一些账务信息往往需要和某些对象关联起来,不同的对象有不同的列,因此列名也是无法确定的,显然我们没有办法配置XML去完成映射规则。再者如果使用存储过程,Hibernate也是无法适应的。这些都不是致命的,最为致命的问题是性能。Hibernate屏蔽了SQL,那就意味着只能全表映射,但是一张表可能有几十到上百个字段,而你感兴趣的只有2个,这是Hibernate无法适应的。尤其是在大型网站系统,对传输数据有严格规定,不能浪费带宽的场景下就更为明显了。有很复杂的场景需要关联多张表,Hibernate全表逐级取对象的方法也只能作罢,写SQL还需要手工的映射取数据,这带来了很大的麻烦。此外,如果我们需要优化SQL,Hibernate也是无法做到的。

我们稍微总结一下Hibernate的缺点:● 全表映射带来的不便,比如更新时需要发送所有的字段。● 无法根据不同的条件组装不同的SQL。● 对多表关联和复杂SQL查询支持较差,需要自己写SQL,返回后,

需要自己将数据组装为POJO。● 不能有效支持存储过程。● 虽然有HQL,但是性能较差。大型互联网系统往往需要优化SQL,

而Hibernate做不到。

在当今大型互联网中,灵活、SQL优化,减少数据的传递是最基本的优化方法,显然Hibernate无法满足我们的要求。这时MyBatis框架诞生了,它提供了更灵活、更方便的方法,弥补了Hibernate的这些缺陷。1.4 MyBatis

为了解决Hibernate的不足,一个半自动映射的框架MyBatis应运而生。之所以称它为半自动,是因为它需要手工匹配提供POJO、SQL和映射关系,而全表映射的Hibernate只需要提供POJO和映射关系便可。

历史上,MyBatis的前身是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github,所以目前MyBatis是由Github维护的。

iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBatis提供的持久层框架包括SQL Maps和DAO(Data Access Objects)。它能很好地解决Hibernate遇到的问题。与Hibernate不同的是,它不单单要我们提供映射文件,还需要我们提供SQL语句。MyBatis所需要提供的映射文件包含以下三个部分。● SQL。● 映射规则。● POJO。

在MyBatis里面,你需要自己编写SQL,虽然比Hibernate配置得多,但是MyBatis可以配置动态SQL,这就解决了Hibernate的表名根据时间变化,不同的条件下列名不一样的问题。同时你也可以优化SQL,通过配置决定你的SQL映射规则,也能支持存储过程,所以对于一些复杂的和需要优化性能SQL的查询它更加方便,MyBatis几乎能做到JDBC所能做到的所有事情。MyBatis具有自动映射功能。换句话说,在注意一些规则的基础上,MyBatis可以给我们完成自动映射,而无需再写任何的映射规则,这大大提高了开发效率和灵活性。

如图1-3所示为MyBatis的ORM映射模型。图1-3 MyBatis的ORM映射模型

让我们看看如何实现JdbcExample的功能。首先是数据库及其他的基础配置,如代码清单1-6所示。代码清单1-6:mybatis_config.xml

这就是MyBatis的基础配置文件。其次是一个映射文件,也十分简单,如代码清单1-7所示。代码清单1-7:Role.xml

这里我们给出了SQL,但是并没有给出映射规则,因为这里我们使用的SQL列名和POJO的属性名保持一致,这个时候MyBatis会自动提供映射规则,所以省去了这部分的配置工作。再者,我们还需要一个接口,注意仅仅是接口,而无需实现类,如代码清单1-8所示。代码清单1-8:RoleMapper.javapublic interface RoleMapper { public Role getRole(Long id);}

为了使用MyBatis,我们还需要建立SqlSessionFactory,如代码清单1-9所示。代码清单1-9:MyBatisUtil.javapublic class MyBatisUtil { private static SqlSessionFactory sqlSessionFactory = null; public static SqlSessionFactory getSqlSessionFactroy() { InputStream inputStream = null; if (sqlSessionFactory == null) { try { String resource = "mybatis_config.xml"; sqlSessionFactory = new SqlSessionFactoryBuilder().build (Resources.getResourceAsStream(resource)); return sqlSessionFactory; } catch (Exception ex) { System.err.println(ex.getMessage()); ex.printStackTrace(); } } return sqlSessionFactory; }}

现在我们可以用MyBatis来实现代码清单1-1的功能了,如代码清单1-10所示。代码清单1-10:MyBatisExample.javapublic class MyBatisExample { public static void main(String[] args) { SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.getSqlSessionFactroy().openSession(); RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Role role = roleMapper.getRole(1L); System.err.println("role_name = >" + role.getRoleName()); } finally { sqlSession.close(); } } }

这样便完成了MyBatis的代码编写工作,SQL和映射规则都在XML里面进行了分离,而MyBatis更为灵活。你可以自由书写SQL,定义映射规则。此外,MyBatis提供接口编程的映射器只需要一个接口和映射文件便可以运行,消除了在iBatis时代需要SqlSession调度的情况。1.5 什么时候用MyBatis

通过对JDBC、Hibernate和MyBatis的介绍,我们有了一些认识。JDBC的方式在目前而言极少用到,因为你需要提供太多的代码,操作太多的对象,麻烦不说,还极其容易出错,所以这不是一种推荐的方式,在实际开发中直接用JDBC的场景也是很少的。

Hibernate作为较为流行的Java ORM框架,它确实编程简易,需要我们提供映射的规则,完全可以通过IDE生成,同时无需编写SQL确实开发效率优于MyBatis。此外,它也提供了缓存、日志、级联等强大的功能,但是Hibernate的缺陷也是十分明显的,多表关联复杂SQL,数据系统权限限制,根据条件变化的SQL。存储过程等场景使用Hibernate十分不便,而性能又难以通过SQL优化。所以注定了Hibenate只适用于在场景不太复杂,要求性能不太苛刻的时候使用。

如果你需要一个灵活的、可以动态生成映射关系的框架,那么MyBatis确实是一个最好的选择。它几乎可以代替JDBC,拥有动态列、动态表名,存储过程都支持,同时提供了简易的缓存、日志、级联。但是它的缺陷是需要你提供映射规则和SQL,所以它的开发工作量比Hibernate略大一些。

你需要根据项目的实际情况去选择框架。因为MyBatis具有高度灵活、可优化、易维护等特点,所以它目前是大型移动互联网项目的首选框架。

下面各章,我们将分别讨论MyBatis的应用、原理和实践。第2章MyBaits入门

这章的目标很明确,就是带大家入门。我们先准备环境的搭建,然后开始讲述MyBatis的基本构成和应用,并且给出一个可以运行的实例。为了让大家加深理解,我们将讲述MyBatis的核心类和接口对象的生命周期,在理解其生命周期后,我们将优化实例。这章内容应用多于原理,我们在后面的几章中再讨论其实现的原理、架构和方法。2.1 开发环境准备

学习编程是一门实践科学,只有一边编写代码一边学习才会有好的效果,所以需要搭建一个可以运行的学习环境,以便我们实践和探索,所以这节主要带领大家来配置开发环境。2.1.1 下载MyBatis

输入网址https://github.com/mybatis/mybatis-3/releases进入MyBatis的官网,我们就可下载MyBatis,如图2-1所示。图2-1 下载MyBatis

我们可以在这里下载到MyBatis所需的jar包和源码包。讲解MyBatis运行原理和插件的时候常常会用到源码的内容。

使用MyBatis项目可以参考http://mybatis.org/mybatis-3/zh/index.html。

使用MyBatis-Spring项目可以参考http://mybatis.org/spring/zh/index.html。2.1.2 搭建开发环境

无论使用哪一种Java IDE都可以轻松搭建开发环境。这里以Eclipse为例搭建我们的开发环境。我们打开下载得到的MyBatis开发包就可以得到如图2-2所示的目录。图2-2 MyBatis下载包目录

这里的jar文件分为两类,一类是MyBatis本身的jar包,另一类在lib文件夹里。MyBatis项目所依赖的jar包,而pdf文件则是它提供的API文档。我们只需要在Eclipse中引入MyBatis的jar包即可,如图2-3所示。图2-3 引入MyBatis的jar包

这样便完成了MyBatis的环境搭建,我们便可以在项目中使用MyBatis了。2.2 MyBatis的基本构成

认识往往是从表面现象到内在本质的一个探索过程,所以对于MyBatis的掌握,我们从认识“表面现象”——MyBatis的基本构成开始。我们先了解一下MyBatis的核心组件。● SqlSessionFactoryBuilder(构造器):它会根据配置信息或者代

码来生成SqlSessionFactory(工厂接口)。● SqlSessionFactory:依靠工厂来生成SqlSession(会话)。● SqlSession:是一个既可以发送SQL去执行并返回结果,也可以

获取Mapper的接口。● SQL Mapper:它是MyBaits新设计的组件,它是由一个Java接口

和XML文件(或注解)构成的,需要给出对应的SQL和映射规则。

它负责发送SQL去执行,并返回结果。

用一张图表达它们之间的关联,如图2-4所示。图2-4 MyBatis的构成

这里我们不需要马上明白MyBatis的组件内容,先了解它们之间的先后顺序、流程和基本功能,后面我们会详细讨论它们的用法。2.2.1 构建SqlSessionFactory

每个MyBatis的应用都是以SqlSessionFactory的实例为中心的。SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。但是读者们需要注意SqlSessionFactory是一个工厂接口而不是现实类,它的任务是创建SqlSession。SqlSession类似于一个JDBC的Connection对象。MyBatis提供了两种模式去创建SqlSessionFactory:一种是XML配置的方式,这是笔者推荐的方式;另一种是代码的方式。能够使用配置文件的时候,我们要尽量的使用配置文件,这样一方面可以避免硬编码(hard code),一方面方便日后配置人员的修改,避免重复编译代码。

这里我们的Configuration的类全限定名为org.apache.ibatis.session. Configuration,它在MyBatis中将以一个Configuration类对象的形式存在,而这个对象将存在于整个MyBatis应用的生命期中,以便重复读取和运用。在内存中的数据是计算机系统中读取速度最快的,我们可以解析一次配置的XML文件保存到Configuration类对象中,方便我们从这个对象中读取配置信息,性能高。单例占用空间小,基本不占用存储空间,而且可以反复使用。Configuration类对象保存着我们配置在MyBatis的信息。在MyBatis中提供了两个SqlSessionFactory的实现类,DefaultSqlSessionFactory和SqlSessionManager。不过SqlSessionManager目前还没有使用,MyBatis中目前使用的是DefaultSqlSessionFactory。

让我们看看它们的关系图,如图2-5所示。图2-5 两个SqlSessionFactory现实类的关系图2.2.1.1 使用XML方式构建

这里我们配置一个简易的XML,包含获取数据库连接实例的数据源(DataSource)、决定事务范围和控制方式的事务管理器(TransactionManager)和映射器(SQL Mapper)。XML配置文件的内容后面会详细探讨,这里先给出一个简单的示例,如代码清单2-1所示。代码清单2-1:mybatis-config.xml

对上面的配置做一下说明。● 这里配置了一个别名role,它代表com.learn.chapter2.po.Role,

这样我们就可以在MyBatis上下文中引用它了。● 我们配置了环境内容,它默认使用id是development的环境配

置,包含以下两方面的内容。(1)采用JDBC的事务管理模式。(2)数据库的连接信息。● 配置映射器。

这里引入了一个XML,它的作用是提供SQL和SQL对POJO的映射规则定义,它包含了映射器里面的信息。MyBatis将解析这个XML,来为我们生成映射器。

现在我们用代码实现创建SqlSessionFactory,如代码清单2-2所示。代码清单2-2:生成SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = null; sqlSessionFactory = new SqlSessionFactoryBuilder().build (inputStream);

这里我们创建了一个XML文件输入流,用SqlSessionFactoryBuilder读取XML的信息来创建SqlSessionFactory的对象。

MyBatis的解析程序会将mybatis-config.xml文件配置的信息解析到Configuration类对象里面,然后利用SqlSessionFactoryBuilder读取这个对象为我们创建SqlSession Factory。2.2.1.2 使用代码方式构建

除了使用XML配置的方式创建代码外,也可以使用Java编码来实现,不过并不推荐这个方式,因为修改环境的时候,我们不得不重新编译代码,这样不利于维护。

不过在本书我们依旧讨论其实现方法。和上面XML方式一样我们也要配置别名、数据库环境和映射器。MyBatis已经为我们提供好了对象的类和方法,我们只要熟悉它们的使用即可。首先,构建Configuration类对象。然后,往对象里面注册我们构建SqlSessionFactory所需要的信息便可。

让我们看看代码是如何现实的,如代码清单2-3所示。代码清单2-3:使用代码生成SqlSessionFactory//构建数据库连接池PooledDataSource dataSource = new PooledDataSource();dataSource.setDriver("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");dataSource.setUsername("root");dataSource.setPassword("learn");//构建数据库事务方式TransactionFactory transactionFactory = new JdbcTransactionFactory();//创建了数据库运行环境Environment environment = new Environment("development", transactionFactory, dataSource);//构建Configuration对象Configuration configuration = new Configuration(environment);//注册一个MyBatis上下文别名configuration.getTypeAliasRegistry().registerAlias("role", Role.class);//加入一个映射器configuration.addMapper(RoleMapper.class);//使用SqlSessionFactoryBuilder构建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build (configuration);return sqlSessionFactory;

让我们说明一下上面的代码做了什么。● 初始化了一个数据库连接池。● 定义了JDBC的数据库事务管理方式。● 用数据库连接池和事务管理方式创建了一个数据库运行环境,并

命名为development。● 创建了一个Configuration类对象,并把数据库运行环境注册给它。● 注册一个role的别名。● 加入一个映射器。● 用SqlSessionFactoryBuilder通过Configuration对象创建

SqlSessionFactory。

显然用代码方式和用XML方式只是换个方法实现而已,其本质并无不同。采用代码方式一般是在需要加入自己特性的时候才会用到,例如,数据源配置的信息要求是加密的时候,我们需要把它们转化出来。在大部分的情况下,笔者都不建议你使用这个方式来创建MyBatis的SqlSessionFactory。2.2.2 创建SqlSession

SqlSession是一个接口类,它类似于你们公司前台的美女客服,它扮演着门面的作用,而真正干活的是Executor接口,你可以认为它是公司的工程师。假设我是客户找你们公司干活,我只需要告诉前台的美女客服(SqlSession)我要什么信息(参数),要做什么东西,过段时间,她会将结果给我。在这个过程中,作为用户的我所关心的是:(1)要给美女客服(SqlSession)什么信息(功能和参数)。(2)美女客服会返回什么结果(Result)。

而我不关心工程师(Executor)是怎么为我工作的,只要前台告诉工程师(Executor),工程师就知道如何为我工作,这个步骤对我而言是个黑箱操作。

在MyBatis中SqlSession接口的实现类有两个,分别是DefaultSqlSession和SqlSession Manager。这里我们暂时不深入讨论Executor接口及其涉及的其他类,只关心SqlSession的用法就好。我们构建了SqlSessionFactory,然后生成MyBatis的门面接口SqlSession。SqlSession接口类似于一个JDBC中的Connection接口对象,我们需要保证每次用完正常关闭它,所以正确的做法是把关闭SqlSession接口的代码写在finally语句中保证每次都会关闭SqlSession,让连接资源归还给数据库。如果我们不及时关闭资源,数据库的连接资源将很快被耗尽,系统很快因为数据库资源的匮乏而瘫痪。让我们看看实现的伪代码,如代码清单2-4所示。代码清单2-4:标准SqlSession使用方法//定义SqlSession SqlSession sqlSession = null; try { //打开SqlSession会话 sqlSession = sqlSessionFactory.openSession(); //some code .... sqlSession.commit(); } catch(Exception ex) { System.err.println(ex.getMessage()); sqlSession.rollback(); }finally { //在finally语句中确保资源被顺利关闭 if (sqlSession != null) { sqlSession.close(); } }

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载