深刻淺出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以適用於不一樣的業務場景,以及提供給咱們的擴展。

歡迎掃描下方二維碼,關注個人我的微信公衆號 ~

情情說
相關文章
相關標籤/搜索