深刻浅出MyBatis:JDBC和MyBatis介绍

最近在休陪产假,时间比较零碎,准备看2本书充实下,一本是「深刻浅出MyBatis:技术原理与实践」,一本是「RabbitMQ实战:高效部署分布式消息队列」,为了加深记忆和理解,会进行整理、扩展和记录。php

看书的目标不是把全部的细节都记住,而是从总体上了解一个技术能作什么,包含的特性、基本模块,实现原理和常见使用场景。java

本篇分享MyBatis书籍的第一篇,首先回忆下JDBC的相关概念,了解Java提供的访问数据库最基本的方式,而后介绍下MyBatis的基本特性和核心组件,最后说下书的总体结构,了解后续文章的大体内容。mysql

JDBC相关概念

Java程序都是经过JDBC链接数据库的,经过SQL对数据库编程,JDBC是由SUN公司提出的一些列规范,只定义了接口规范,具体实现由各个数据库厂商去实现,它是一种典型的桥接模式。sql

桥接模式是一种结构型设计模式,它的主要特色是把抽象与行为实现分离开来,分别定义接口,能够保持各部分的独立性以及应对他们的功能扩展。数据库

JDBC规范

所谓规范,就是本身定义了标准接口,作了以下抽象:用Connection表明和数据库的链接,用Statement执行SQL,用ResultSet表示SQL返回的结果,提供了对数据的便利。从Connection能够建立Statement,Statement执行查询获得ResultSet。编程

上面说的Connection、Statement、ResultSet都应该是接口,具体实现由各个数据库提供商提供。有了规范,能够经过统一的接口,访问多种类型的数据库,可随便切换数据库。设计模式

数据库驱动

上面提到,接口的实现由各个厂商提供,那么实现类的类名就会不统一,去建立Connection对象时,代码就会写死某个实现类,切换数据库时,就须要修改代码,这样不太好。为了解决这个问题,抽象了Driver驱动的概念。缓存

Connection con=MySqlConnectionImpl("127.0.0.1",3306,"mi_user",userName,pwd);
复制代码

每一个数据库都须要实现Driver接口,经过Driver可得到数据库链接Connection,经过反射机制动态建立。安全

Class.forName("com.mysql.jdbc.Drier");
复制代码

同一个程序可能访问不一样的数据库,经过DriverManager来管理驱动,Driver在初始化的时候,须要注册到DriverManager中。微信

DriverManager提供了一个getConnection方法,用于创建数据库Connection:

Connection con=DriverManager.getConnection("127.0.0.1",3306,"mi_user",userName,pwd);
复制代码

若是有多个数据库驱动,DriverManager如何区分呢,须要在数据库链接url中指定,好比mysql须要添加jdbc:mysql前缀:

String url= "jdbc:mysql://127.0.0.1:3306/mi_user";
Connection con=DriverManager.getConnection(url,userName,pwd)
复制代码
数据源

数据源DataSource包含链接池和链接池管理2个部分,习惯上称为链接池。在系统初始化的时候,将数据库链接做为对象存储在内存中,当须要访问数据库时,从链接池中取出一个已创建的空闲链接对象。

使用数据源,获取其DataSource对象,经过该对象动态的获取数据库链接。另外,DataSource对象能够注册到名字服务(JNDI)中,能够经过名字服务得到DataSource对象,无需硬性编码驱动。

DriverManager是JDBC1提供的,DataSource是JDBC2新增的功能,提供了更好的链接数据源的方法。

对比Hibernate和MyBatis

经过上面的介绍,传统的JDBC编程给咱们带来了链接数据库的功能,但其工做量相对较大,首先链接,而后处理JDBC底层事务,处理数据类型,还要对可能产生的异常进行捕捉处理并正确的关闭资源。

实际工做中,不多使用JDBC进行编程,提出了ORM模型,主要解决数据库数据和POJO对象的相互映射。

Hibernate和Mybatis都是ORM模型,Hibernate提供的是一种全表映射的模型,对JDBC的封装程度比较高。但Hibernate也有很多缺点,列举以下:

  • 全表映射带来的不便,好比更新时须要发送全部的字段;
  • 没法根据不一样的条件组装不一样的SQL;
  • 对多表关联和复杂SQL查询支持较差,须要本身写SQL,返回后,须要本身将数据组装为POJO;
  • 不能有效支持存储过程;
  • 虽然有HQL,但性能较差,大型互联网系统每每须要优化SQL,而Hibernate作不到。

大型互联网环境中,灵活、SQL优化,减小数据的传递是最基本的优化方法,Hibernate没法知足要求,而MyBatis提哦给你了灵活、方便的方式,是一个半自动映射的框架。

MyBatis须要手工匹配提供POJO、SQL和映射关系,而全表映射的Hibernate只须要提供POJO和映射关系。

MyBatis能够配置动态SQL,能够解决Hibernate的表名根据时间变化,不一样的条件下列明不同的问题。能够优化SQL,经过配置决定SQL映射规则,也能支持存储过程,对于一些复杂和须要优化性能的SQL的查询它更加方便。

核心组件

核心组件主要包括如下几个:

  • SqlSessionFactoryBuilder:会根据配置信息或代码来生成SqlSessionFactory;
  • SqlSessionFactory:依靠工厂来生成SqlSession;
  • SqlSession:是一个既能够发送SQL去执行并返回结果,也能够获取Mapper的接口;
  • SQL Mapper:是MyBatis新设计的组件,由一个Java接口和XML文件构成,须要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。
构建SqlSessionFactory

每一个MyBatis应用都是以SqlSessionFactory的实例为中心的,它的任务是建立SqlSession。SqlSesion相似于一个JDBC的Connection对象。

提供了2种方式建立SqlSessionFactory:一种是XML配置的方式,一种是代码的方式,推荐使用XML配置的方式。

定义mybatis-config.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>
 <properties resource="application.properties">
 </properties>
 
 <!-- 定义别名 -->
 <typeAliases>
 <typeAlias alias="role" type="com.learn.chapter2.po.Role"/>
 </typeAliases>
 
 <!-- 定义数据库信息.默认使用development数据库构建环境 -->
 <environments default="development">
    <environment id="development">
    <!-- 采用jdbc事务管理 -->
        <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="com\learn\chapter2\mapper\roleMapper.xml"/>
 </mappers>
</configuration>
复制代码

建立SqlSessionFactory

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory  sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
复制代码
建立SqlSession

SqlSession是一个接口类,扮演者门面的做用,真正干活的是Executor接口。须要保证每次用完正常关闭它。

SqlSession sqlSession=null;
try{
    sqlSession=sqlSessionFactory.openSession();
    //some code
    sqlSession.commit();
} catch(Exception ex){
    sqlSession.roolback();
} finally{
    if(sqlSession!=null){
        sqlSession.close();
    }
}
复制代码
映射器

映射器是由Java接口和XML文件(或注解)共同组成的,做用以下:

  • 定义参数类型
  • 描述缓存
  • 描述SQL语句
  • 定义查询结果和POJO的映射关系

首先,定义Java接口:

public interface RoleMapper{
    public Role getRole(Long id);
}
复制代码

而后,定义映射XML文件,RoleMapper.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">
 
 <mapper namespace ="com.learn.chapter2.mapper.RoleMapper">
    <select id="getRole" paramterType="long" resultType="role" >
        select id,role_name as roleName , note from t_role where id=#{id}
    </select>
 </mapper>
复制代码

POJO对象Role的定义比较简单,就不列出了。#{id}为这条SQL的参数,SQL列的别名和POJO的属性名称保持一致,会把这条语句的查询结果自动映射到Role属性上,这就是自动映射。

执行查询

RoleMapper roleMapper=sqlSession.getMapper(RoleMapper.class);
Role role=roleMapper.getRole(1L);
String roleName=role.getRoleName();
复制代码
组件生命周期

SqlSessionFactory在MyBatis应用的整个生命周期中,每一个数据库只对应一个SqlSessionFactory,能够实现一个工具类,以单例模式获取该对象。

SqlSession的生命周期在请求数据库处理事务的过程当中,它是一个线程不安全的对象,在涉及多线程的时候要特别小心。它存活于一个应用的请求和操做,能够执行多条SQL,保证事务的一致性。

Mapper的做用是发送SQL,而后返回须要的结果,或者执行SQL修改数据库的数据,因此它应该在一个SqlSession事务方法以内,如同JDBC中一条SQL语句的执行,它最大的范围和SqlSession是相同的。

书的总体结构

本书分为3个部分,依次介绍了MyBatis的基础应用、原理及插件开发、实战应用。

基础应用

主要介绍如何高效地使用MyBatis:

  • MyBatis特性
  • 核心组件及其生命周期
  • MyBatis配置
  • 映射器
  • 动态SQL
MyBatis原理

深刻源码理解MyBatis的内部运行原理以及插件的开发方法和技巧:

  • 介绍MyBatis的解析和运行原理,将了解到SqlSession的构建方法,以及四大对象是如何工做的
  • 介绍MyBatis的插件
实战应用

主要讲解MyBatis的一些实用的场景:

  • 介绍MyBatis-Spring,讲解如何在Spring项目中集成MyBatis应用
  • 介绍MyBatis的实用场景,精选一些典型场景,解析每一个场景下,开发人员须要注意避免的一些错误和性能上的损失

下篇会介绍MyBatis的相关配置,更好的配置MyBatis以适用于不一样的业务场景,以及提供给咱们的扩展。

欢迎扫描下方二维码,关注个人我的微信公众号 ~

情情说
相关文章
相关标签/搜索