1. 程式人生 > >mybatis的動態查詢

mybatis的動態查詢

這裡是修真院後端小課堂,每篇分享文從

【背景介紹】【知識剖析】【常見問題】【解決方案】【編碼實戰】【擴充套件思考】【更多討論】【參考文獻】

八個方面深度解析後端知識/技能,本篇分享的是:

【mybatis的動態查詢】

大家好,我是IT修真院深圳分院第10期的JAVA學員,一枚正直純潔善良的java程式設計師。

今天給大家分享一下,修真院官網Java任務5,深度思考中的知識點—mybatis的動態查詢

 

1.背景介紹

MyBatis是支援普通SQL查詢,儲存過程和高階對映的優秀持久層框架。MyBatis消除了幾乎所有的JDBC程式碼如引數的手工設定以及結果集的檢索。MyBatis 使用簡單的 XML或註解用於配置和原始對映,將介面和JavaBean對映成資料庫中的記錄。

每個MyBatis應用程式主要都是使用SqlSessionFactory例項的,一個SqlSessionFactory例項可以通過SqlSessionFactoryBuilder獲得。SqlSessionFactoryBuilder可以從一個xml配置檔案或者一個預定義的配置類的例項獲得。

 

Mybatis的特點:

簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單的安裝只要兩個jar檔案+配置幾個sql對映檔案。

靈活:mybatis不會對應用程式或者資料庫的現有設計強加任何影響。 sql寫在xml裡,便於統一管理和優化。

解除sql與程式程式碼的耦合:通過提供DAL層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和程式碼的分離,提高了可維護性。

半自動對映框架:其被稱為半自動是因為需要手工配置POJO,sql和對映關係,所有的功能通過編寫SQL來實現。

提供了對底層JDBC資料訪問的封裝

提供強大的資料對映功能(傳入引數對映和結果資料對映)

 

Mybtais執行的總體流程

(1)載入配置並初始化

觸發條件:載入配置檔案

處理過程:將SQL的配置資訊載入成為一個個MappedStatement物件(包括了傳入引數對映配置、執行的SQL語句、結果對映配置),儲存在記憶體中。

這裡說下,一個MappedStatement物件對應Mapper配置檔案中的一個select/update/insert/delete節點,主要描述的是一條SQL語句。

(2)接收呼叫請求

觸發條件:呼叫Mybatis提供的API

傳入引數:SQL的ID和傳入引數物件

處理過程:將請求傳遞給下層的請求處理層進行處理。

 

(3)處理操作請求

觸發條件:API介面層傳遞請求過來

傳入引數:SQL的ID和傳入引數物件

處理過程:

(A)根據SQL的ID查詢對應的MappedStatement物件。

(B)根據傳入引數物件解析MappedStatement物件,得到最終要執行的SQL和執行傳入引數。

(C)獲取資料庫連線,根據得到的最終SQL語句和執行傳入引數到資料庫執行,並得到執行結果。

(D)根據MappedStatement物件中的結果對映配置對得到的執行結果進行轉換處理,並得到最終的處理結果。

(E)釋放連線資源。

(4)返回處理結果:

將操作資料庫的結果按照對映的配置進行轉換,可以轉換成HashMap、JavaBean或者基本資料型別,並將最終結果返回。

 

 

2.知識剖析

 

1.mybatis配置檔案

2.動態SQL語句

 

配置檔案標籤

1、Properties屬性:用來載入屬性配置檔案。

Mybatis將按照下面的順序來載入屬性:

   (1) 首先會讀取在property標籤中定義的屬性。

   (2) 然後會讀取在properties標籤中通過resource或url載入時的屬性,它會覆蓋已讀取得同名屬性。

   (3) 最後會讀取sql中parameterType傳遞過來的屬性,它會覆蓋已讀取的同名屬性。

因此,通過方法引數傳遞的屬性具有最高優先順序,resource/url 屬性中指定的配置檔案次之,最低優先順序的是 properties 屬性中指定的屬性。

 

2、settings全域性引數配置:Mybatis框架在執行時可以調整一些執行引數,比如:開啟二級快取、開啟延遲載入等。

 

3、typeAliases類型別名:類型別名是為 Java 型別設定一個短的名字。它只和 XML 配置有關,存在的意義僅在於用來減少類完全限定名的冗餘。

4、配置環境(environments):MyBatis 可以配置成適應多種環境,這種機制有助於將 SQL 對映應用於多種資料庫之中,例如,開發、測試和生產環境需要有不同的配置;

不過:儘管可以配置多個環境,每個 SqlSessionFactory 例項只能選擇其一。所以,如果我們想連線兩個資料庫,就需要建立兩個 SqlSessionFactory 例項,每個資料庫對應一個。

 

為了指定建立哪種環境,只要將它作為可選的引數傳遞給 SqlSessionFactoryBuilder 即可。可以接受環境配置的兩個方法簽名是:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);

如果忽略了環境引數,那麼預設環境將會被載入。

 

5、事務管理器(transactionManager)

 

在 MyBatis 中有兩種型別的事務管理器(也就是 type=”[JDBC|MANAGED]”):

 

JDBC – 這個配置就是直接使用了 JDBC 的提交和回滾設定,它依賴於從資料來源得到的連線來管理事務作用域。

MANAGED – 這個配置幾乎沒做什麼。它從來不提交或回滾一個連線,而是讓容器來管理事務的整個生命週期(比如 JEE 應用伺服器的上下文)。 預設情況下它會關閉連線,然而一些容器並不希望這樣,因此需要將 closeConnection 屬性設定為 false 來阻止它預設的關閉行為。

 

 

6、typeHandlers型別處理器

無論是 MyBatis 在預處理語句(PreparedStatement)中設定一個引數時,還是從結果集中取出一個值時, 都會用型別處理器將獲取的值以合適的方式轉換成 Java 型別。即專門用來解決資料庫中的資料型別和Java中的資料型別之間的轉化問題。

mybatis有一系列的預設的型別處理器,所以在平時開發的時候我們不用去關心java到資料庫的型別轉化關係,mybatis都幫我們把這些工作完成了。當然我們也可以重寫型別處理器或建立你自己的型別處理器來處理不支援的或非標準的型別。

 

 

動態SQL語句

       MyBatis 的強大特性之一便是它的動態 SQL。mybatis 的動態sql語句是基於OGNL表示式的。可以方便的在 sql 語句中實現某些邏輯. 總體說來mybatis 動態SQL 語句主要有以下幾類:

1. if 語句 (簡單的條件判斷)

2. choose (when,otherwize) ,相當於java 語言中的 switch 

3. trim :

(1)只有prefix,suffix 表示在trim標籤包裹的部分的前面或者後面新增內容

(2)只有prefixOverrides,suffixOverrides 表示刪除

4. where (主要是用來簡化sql語句中where條件判斷的,能智慧的處理 and /or ,不必擔心多餘導致語法錯誤)

 

 

5. set (主要用於更新時):

1)、程式執行時,將生成set關鍵字

2)、會過濾掉最後一個update語句的","

6. foreach (在實現 mybatis in 語句查詢時特別有用)

1)、collection表示如何來得到這個集合,如果傳入的直接為一個List,那麼collection值就為list。

  2)、item表示集合中每一個元素進行迭代時的別名,比如item為value,那麼,每次獲取的都使用#{value}即可

  3)、index指定一個名字,用於表示在迭代過程中,每次迭代到的位置

  4)、open表示該語句以什麼開始

  5)、separator表示在每次進行迭代之間以什麼符號作為分隔符

  6)、close表示以什麼結束

 

 

 

3.常見問題

如何配置mybatis的逆向工程,生成程式碼?

 

 

4.解決方案

1)新建一個和原工程檔名字相同的專案,建立一個xml配置檔案:

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
    PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
    "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

    <generatorConfiguration>
        <context id="testTables" targetRuntime="MyBatis3">
            <commentGenerator>
                <!-- 是否去除自動生成的註釋 true:是 : false:否 -->
                <property name="suppressAllComments" value="true" />
            </commentGenerator>
            <!--資料庫連線的資訊:驅動類、連線地址、使用者名稱、密碼 -->
            <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                            connectionURL="jdbc:mysql:///more_pineapple" userId="root"
                            password="root123">
            </jdbcConnection>
            <!-- 預設false,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer,為 true時把JDBC DECIMAL 和
                NUMERIC 型別解析為java.math.BigDecimal -->
            <javaTypeResolver>
                <property name="forceBigDecimals" value="false" />
            </javaTypeResolver>

            <!-- targetProject:生成PO類的位置 -->
            <javaModelGenerator targetPackage="src.main.java.com.jnshu.backendsystem.pojo"
                                targetProject=".\src">
                <!-- enableSubPackages:是否讓schema作為包的字尾 -->
                <property name="enableSubPackages" value="false" />
                <!-- 從資料庫返回的值被清理前後的空格 -->
                <property name="trimStrings" value="true" />
            </javaModelGenerator>
            <!-- targetProject:mapper對映檔案生成的位置 -->
            <sqlMapGenerator targetPackage="src.main..resources.mappers"
                             targetProject=".\src">
                <!-- enableSubPackages:是否讓schema作為包的字尾 -->
                <property name="enableSubPackages" value="false" />
            </sqlMapGenerator>
            <!-- targetPackage:mapper介面生成的位置 -->
            <javaClientGenerator type="XMLMAPPER"
                                 targetPackage="src.main.java.com.jnshu.backendsystem.dao"
                                 targetProject=".\src">
                <!-- enableSubPackages:是否讓schema作為包的字尾 -->
                <property name="enableSubPackages" value="false" />
            </javaClientGenerator>
            <!-- 指定資料庫表 -->
            <table schema="" tableName="banner_show"></table>
            <table schema="" tableName="company_info"></table>
            <table schema="" tableName="company_produce"></table>
            <table schema="" tableName="position_info"></table>
            <table schema="" tableName="module_table"></table>
        </context>
    </generatorConfiguration>

 

在配置檔案中,配置生成工程檔案的路徑、資料庫使用者名稱、密碼、表字段等。

 

然後新建一個執行類

com.jnshu.mybatisorg.mybatis.generator.api.MyBatisGeneratororg.mybatis.generator.config.Configurationorg.mybatis.generator.config.xml.ConfigurationParserorg.mybatis.generator.internal.DefaultShellCallbackjava.io.Filejava.util.ArrayListjava.util.ListGeneratorSqlmap {
    () Exception{

        List<String> warnings = ArrayList<String>()overwrite = File configFile = File()ConfigurationParser cp = ConfigurationParser(warnings)Configuration config = cp.parseConfiguration(configFile)DefaultShellCallback callback = DefaultShellCallback(overwrite)MyBatisGenerator myBatisGenerator = MyBatisGenerator(configcallbackwarnings)myBatisGenerator.generate()}
    (String[] args) Exception {
        {
            GeneratorSqlmap generatorSqlmap = GeneratorSqlmap()generatorSqlmap.generator()} (Exception e) {
            e.printStackTrace()}

    }

}

 

然後執行程式就可以了,就會生出相對應的實體層、dao層和對映層。

 

5.編碼實戰

 

6.擴充套件思考

 

7.參考文獻

 

連結:https://baike.baidu.com/item/MyBatis/2824918?fr=aladdin

作者:百度百科

連結:https://www.w3cschool.cn/

作者:w3cschool

連結:http://www.mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

作者:Mybatis

連結: https://blog.csdn.net/happyheng/article/details/70232136

 

8.更多討論

1)mybatis動態查詢的好處有哪些?

mybatis的動態查詢,可以根據輸入引數,選擇相對應的條件,對結果進行篩選,這個過程是動態的,可以變化的,並不是固定不變的。

 

2)在真實開發的過程當中,如何處理多選引數?資料庫mapper檔案該如何設定?

select
    c.company_id,c.company_name,c.company_logo,c.city,c.area,c.company_industry,c.financing_scale,(p.position_id)
    as numberOfPositions
    from company_info c,position_info p
    c.company_id=p.company_id AND p.is_online = 1
        AND c.company_name LIKE CONCAT('%',#{companyName},'%')
        AND c.city IN
            #{city}
            AND c.company_industry IN
            #{companyIndustry}
            AND c.financing_scale IN
            #{financingScale}
            GROUP BY c.company_id

 

 

3)如何遍歷傳過來的陣列?

可以使用foreach標籤遍歷

AND c.financing_scale IN
    #{financingScale}

 

  

今天的分享就到這裡啦,歡迎大家點贊、轉發、留言、拍磚~

 

技能樹.IT修真院“我們相信人人都可以成為一個工程師,現在開始,找個師兄,帶你入門,掌控自己學習的節奏,學習的路上不再迷茫”。

 

這裡是技能樹.IT修真院,成千上萬的師兄在這裡找到了自己的學習路線,學習透明化,成長可見化,師兄1對1免費指導。快來與我一起學習吧~我的邀請碼:23656198,或者你可以直接點選此連結:http://www.jnshu.com/login/1/23656198

 

 

PPT連結 視訊連結

更多內容,可以加入IT交流群565734203與大家一起討論交流

這裡是技能樹·IT修真院:https://www.jnshu.com,初學者轉行到網際網路的聚集地