Mybatis教程及使用配置

Mybatis教程及使用配置

一.Mybatis簡介
MyBatis由Clinton Begin 在2002 年創建,其後,捐獻給了Apache基金會,成立了iBatis 項目。2010 年5 月,將代碼庫遷至Google Code,並更名爲MyBatis。
MyBatis 是一個可以自定義SQL、存儲過程和高級映射的持久層框架。MyBatis 只使用簡單的XML 和註解來配置和映射基本數據類型、Map 接口和POJO 到數據庫記錄。相對Hibernate和Apache OJB等“一站式”ORM解決方案而言,Mybatis 是一種“半自動化”的ORM實現。
二.從JDBC到Mybatis
1.  JDBC查詢數據庫數據,一般需要以下七個步驟:
(1)  加載JDBC驅動
(2)  建立並獲取數據庫連接
(3)  創建 JDBC Statements 對象
(4)  設置SQL語句的傳入參數
(5)  執行SQL語句並獲得查詢結果
(6)  對查詢結果進行轉換處理並將處理結果返回
(7)  釋放相關資源(關閉Connection,關閉Statement,關閉ResultSet)
實現JDBC有七個步驟,哪些步驟是可以進一步封裝的,減少我們開發的代碼量?
2.  JDBC演變到Mybatis過程
第一步優化:連接獲取和釋放
問題描述:通過JDBC的方式數據庫連接頻繁的開啓和關閉本身就造成了資源的浪費,影響系統的性能;但是現在連接池多種多樣,可能存在變化,有可能採用DBCP的連接池,也有可能採用容器本身的JNDI數據庫連接池。
解決問題:數據庫連接的獲取和關閉我們可以使用數據庫連接池來解決資源浪費的問題,通過連接池就可以反覆利用已經建立的連接去訪問數據庫了,減少連接的開啓和關閉的時間。
同時通過DataSource進行隔離解耦,統一從DataSource裏面獲取數據庫連接,DataSource具體由DBCP實現還是由容器的JNDI實現都可以,將DataSource的具體實現通過讓用戶配置來應對變化。
第二步優化:SQL統一存取
問題描述:通過JDBC的方式,可讀性很差,不利於維護以及做性能調優;改動Java代碼需要重新編譯、打包部署。不利於取出SQL在數據庫客戶端執行(取出後還得刪掉中間的Java代碼,編寫好的SQL語句寫好後還得通過+號在Java進行拼湊)。
     解決問題:把SQL語句統一集中放到配置文件,通過SQL語句的key值去獲取對應的SQL語句。
第三步優化:傳入參數映射和動態SQL
問題描述:很多情況下,我們都可以通過在SQL語句中設置佔位符來達到使用傳入參數的目的,這種方式本身就有一定侷限性,它是按照一定順序傳入參數的,要與佔位符一一匹配。但是,如果我們傳入的參數是不確定的(比如列表查詢,根據用戶填寫的查詢條件不同,傳入查詢的參數也是不同的,有時是一個參數、有時可能是三個參數),那麼我們就得在後臺代碼中自己根據請求的傳入參數去拼湊相應的SQL語句,這樣的話還是避免不了在Java代碼裏面寫SQL語句的命運。
解決問題:通過專門的SQL解析器來解析SQL語句,SQL語句經過解析後就可以動態的生成符合上下文的SQL語句,同時使用#變量名#表示佔位符變量,使用$變量名$表示非佔位符變量
第四步優化:結果映射和結果緩存
問題描述:執行SQL語句、獲取執行結果、對執行結果進行轉換處理、釋放相關資源是一整套下來的。假如是執行查詢語句,那麼執行SQL語句後,返回的是一個ResultSet結果集,這個時候我們就需要將ResultSet對象的數據取出來,不然等到釋放資源時就取不到這些結果信息了。我們從前面的優化來看,以及將獲取連接、設置傳入參數、執行SQL語句、釋放資源這些都封裝起來了,只剩下結果處理這塊還沒有進行封裝,如果能封裝起來,每個數據庫操作都不用自己寫那麼一大堆Java代碼,直接調用一個封裝的方法就可以搞定了
解決問題:一般對執行結果的有哪些處理,有可能將結果不做任何處理就直接返回,也有可能將結果轉換成一個JavaBean對象返回、一個Map返回、一個List返回等等,結果處理可能是多種多樣的。從這裏看,我們必須告訴SQL處理器兩點:第一,需要返回什麼類型的對象;第二,需要返回的對象的數據結構怎麼跟執行的結果映射,這樣才能將具體的值copy到對應的數據結構上。
      接下來,我們可以進而考慮對SQL執行結果的緩存來提升性能。緩存數據都是key-value的格式,那麼這個key怎麼來呢?怎麼保證唯一呢?即使同一條SQL語句幾次訪問的過程中由於傳入參數的不同,得到的執行SQL語句也是不同的。那麼緩存起來的時候是多對。但是SQL語句和傳入參數兩部分合起來可以作爲數據緩存的key值。
第五步優化:解決重複SQL語句問題
問題描述:將所有SQL語句都放到配置文件中,這個時候會遇到一個SQL重複的問題,幾個功能的SQL語句其實都差不多,有些可能是SELECT後面那段不同、有些可能是WHERE語句不同。有時候表結構改了,那麼我們就需要改多個地方,不利於維護。
解決問題:通過將SQL片段模塊化,將重複的SQL片段獨立成一個SQL塊,然後在各個SQL語句引用重複的SQL塊,這樣需要修改時只需要修改一處即可。
 3.  優化的總結
對JDBC的優化和封裝:
(1) 使用數據庫連接池對連接進行管理
(2) SQL語句統一存放到配置文件
(3) SQL語句變量和傳入參數的映射以及動態SQL
(4) 動態SQL語句的處理
(5) 對數據庫操作結果的映射和結果緩存
(6) SQL語句的重複使用
三.框架整體設計
1.       總體流程

mybatis_1  

(1)加載配置並初始化
觸發條件:加載配置文件
          配置來源於兩個地方,一處是配置文件,一處是Java代碼的註解,將SQL的配置信息加載成爲一個個MappedStatement對象(包括了傳入參數映射配置、執行的SQL語句、結果映射配置),存儲在內存中。
(2)接收調用請求
觸發條件:調用Mybatis提供的API
      傳入參數:爲SQL的ID和傳入參數對象
處理過程:將請求傳遞給下層的請求處理層進行處理。
(3)處理操作請求
 觸發條件:API接口層傳遞請求過來
                      傳入參數:爲SQL的ID和傳入參數對象
                      處理過程:
      (A)根據SQL的ID查找對應的MappedStatement對象。
      (B)根據傳入參數對象解析MappedStatement對象,得到最終要執行的SQL和執行傳入參數。
      (C)獲取數據庫連接,根據得到的最終SQL語句和執行傳入參數到數據庫執行,並得到執行結果。
      (D)根據MappedStatement對象中的結果映射配置對得到的執行結果進行轉換處理,並得到最終的處理結果。
      (E)釋放連接資源。
 (4)返回結果處理
   將最終的處理結果返回
 
2.       功能架構設計
  mybatis_2
把Mybatis的功能架構分爲三層:
(1)API接口層:提供給外部使用的接口API,開發人員通過這些本地API來操縱數據庫。接口層一接收到調用請求就會調用數據處理層來完成具體的數據處理。
(2)數據處理層:負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次數據庫操作。
(3)基礎支撐層:負責最基礎的功能支撐,包括連接管理、事務管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來作爲最基礎的組件。爲上層的數據處理層提供最基礎的支撐。
 
 
 
3.       框架架構設計
mybatis_3
框架架構講解:
(1)加載配置:配置來源於兩個地方,一處是配置文件,一處是Java代碼的註解,將SQL的配置信息加載成爲一個個MappedStatement對象(包括了傳入參數映射配置、執行的SQL語句、結果映射配置),存儲在內存中。
(2)SQL解析:當API接口層接收到調用請求時,會接收到傳入SQL的ID和傳入對象(可以是Map、JavaBean或者基本數據類型),Mybatis會根據SQL的ID找到對應的MappedStatement,然後根據傳入參數對象對MappedStatement進行解析,解析後可以得到最終要執行的SQL語句和參數。
(3) SQL執行:將最終得到的SQL和參數拿到數據庫進行執行,得到操作數據庫的結果。
(4)結果映射:將操作數據庫的結果按照映射的配置進行轉換,可以轉換成HashMap、JavaBean或者基本數據類型,並將最終結果返回。
  
 
四.Mybatis入門
每一個Mybatis應該都是以一個SqlSessionFactory實例爲中心的,一個SqlSessionFactory實例都可以使用SqlSessionFactoryBuilder來創造。從配置類中創造的定製SqlSessionFactoryBuilder 實例,可以使用XML配置文件來生成一個SqlSessionFactory 實例。
1.       從xml中創造SqlSessionFactory
MyBatis 有一個Resources 通用類,類中有許多方法可以簡單地從類路徑和其他地址中加載資源。
String resource = "org/mybatis/example/Configuration.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlMapper = new SqlSessionFactoryBuilder().build(reader);
 
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/XXMapper.xml"/>
</mappers>
</configuration>
2.       不使用xml文件新建SqlSessionFactory
DataSource dataSource = DataSourceFactory.getDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment =
new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(XXMapper.class);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(configuration);
3.       使用SqlSessionFactory獲取SqlSession
通過一個SqlSessionFactory,就可以獲取一個SqlSession實例,SqlSession包含了針對數據庫執行語句的每一個方法,直接使用SqlSession執行已經映射的每一個SQL語句:
SqlSession session = sqlSessionFactory.openSession();
try {
XXMapper mapper = session.getMapper(XXMapper.class);
XX  xx= mapper.selectXx (101);
} finally {
session.close();
五.探究SQL映射語句
接下來先看一個簡單的demo,來完成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="com.coin.dao.PersonDao">
         <select id="getPerson" resultType="Person" parameterType="long">
            SELECT id,name
            FROM T_Person
            WHERE id = #{id}
</select></mapper>
可以用下列語句簡單地針對Mapper 接口進行調用上面文件,代碼如下:
PersonDao mapper = session.getMapper(PersonDao.class);
Person p= mapper.getPerson (1);
 
還有一個關於Mapper 類的技巧。它們的映射語句完全不需要使用XML 來配置,可以使用JAVA 註解方式來取代。比如,上面的XML 語句可以替換爲:
public interface PersonDao {
@Select("SELECT id,name
            FROM T_Person
            WHERE id = #{id}
")
Person  getPerson (int id);
 
總結:註解是非常簡單明瞭的,但是JAVA 註解既有侷限性,在語句比較複雜的情況下又比較容易混亂。所以,如果你的語句比較複雜,最好還是使用XML 來映射語句。
六.作用域和生命週期
1.       SqlSessionFactoryBuilder
這個類可以被初始,使用和丟棄,因爲如果已經創建好一個SqlSessionFactory後就不用再保留它,所以SqlSessionFactoryBuilder的最好作用域是方法體內的。
2.       SqlSessionFactory
一旦創建,SqlSessionFactory 就會在整個應用過程中始終存在。所以沒有理由去銷燬和再創建它,一個應用運行中也不建議多次創建SqlSessionFactory。因此SqlSessionFactory最好的作用域是Application。可以結合使用Google Guice 或Spring 來進行依賴反射。這些框架允許你生成管理器來管理SqlSessionFactory 的單例生命週期。
3.       SqlSession
每個線程都有自己的SqlSession 實例,SqlSession 實例是不能被共享,也是不是線程安全的。因此最好使用Request 作用域或者方法體作用域。比如說在Servlet 中的HttpSession 中。如果你正在使用WEB 框架,應該讓SqlSession 跟隨HTTP 請求的相似作用域。也就是說,在收到一個HTTP 請求過後,打開SqlSession,等返回一個迴應以後,立馬關掉這個SqlSession。關閉SqlSession 是非常重要的。你必須要確保SqlSession 在finally 方法體中正常關閉。可以使用下面的標準方式來關閉:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
使用這種模式來貫穿你的所有代碼,以確保所有數據庫資源都被完全關閉。[這是假定不是使用你自己的數據庫連接,而是使用MyBatis 來管理你的數據庫連接資源]。
4.       Mapper實例
Mapper是一種創建用於綁定映射語句的接口。Mapper接口的實例是用SqlSession來獲得的,所以Mapper 實例作用域像SqlSession 一樣,使用請求作用域。在方法被調用的時候調用Mapper實例,然後使用後,就會自動銷燬掉,而不需要使用明確的註銷。下面例子演示如何操作:
SqlSession session = sqlSessionFactory.openSession();
try {
PersonDao mapper = session.getMapper(PersonDao.class);
// do work
} finally {
session.close();
七.Mapper的XML配置文件
Mapper的XML配置文件包含一些設置和屬性,用於增強Mybatis的動作。Configuration的各個節點配置如下:
mybatis_4
1.       屬性(properties)
JAVA 屬性文件就可以配置直觀的、可代替的屬性,或者是屬性項的子項。比如:
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="test"/>
<property name="password" value="test/>
</properties>
通過動態配置,這些屬性都可以用替換整個文件的值。例如:
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
例子中的usrname 和password 將被屬性文件中設置的值所替換, driver 和value 屬性也將被config.properties 文件中值所替換,這爲配置提供了多種選擇。
屬性值也可以設入到SqlSessionBuilder.build()方法中,例如:
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory =
sqlSessionFactoryBuilder.build(reader, environment, props);
如果一個屬性項在多個地方出現,那MyBatis 將按以下順序加載:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章