mybatis

mybatis第一天 mybatis基礎知識 

教學思路:

整個教學思路以訂單商品的項目作爲驅動。

mybatis第一天:基礎知識

  mybatis是一個java持久層框架,java中操作關係型 數據庫用的是jdbcmybatis是對jdbc的一個封裝

1、從一個jdbc程序開始,通過jdbc 程序找到使用原生態的jdbc開發程序,存在哪些問題??通過學習mybatis,mybatis是如何解決這些問題。

2、mybatis的架構(重點)

3、mybatis的入門程序(重點)

      實現 用戶的查詢、添加、修改、刪除。

4、mybatis開發dao的兩種方法。(重點)

         原始的dao開發方式(dao接口和dao實現都需要編寫)

         mapper代理方式(只需要寫dao接口)

5、輸入映射類型和輸出映射類型。

6、動態sql

 

 第二天:高級知識

 

         高級映射查詢(一對一、一對多、多對多)(重點)

         查詢緩存

         延遲加載

         mybatis和spring整合(重點)

         mybatis逆向工程 。

1       開發環境

jdk1.7.0_72

eclipse:eclipse-3.7-indigo

mysql:mysql5.1

 

1.1     創建數據庫

 

 

先導入sql_table.sql,再導入sql_data.sql(記錄系統的初始化數據)

通常需要提供初始化數據的數據庫腳本。

 

 

2       jdbc編程中問題

         企業開發中,根據項目大小、特點進行技術選型 ,jdbc操作數據庫時效率是很高的,jdbc也是技術選型的參考。

        

2.1         jdbc程序

參考教案

需要數據庫的驅動包:

 

上邊是mysql的驅動,下邊是oracle的驅動。

 

 

2.2     jdbc問題總結

1、數據庫連接頻繁的創建和關閉,缺點浪費數據庫的資源,影響操作效率

設想:使用數據庫連接池

 

2、sql語句是硬編碼,如果需求變更需要修改sql,就需要修改java代碼,需要重新編譯,系統不易維護。

設想:將sql語句 統一配置在文件中,修改sql不需要修改java代碼。

 

3、通過preparedStatement向佔位符設置參數,存在硬編碼( 參數位置,參數)問題。系統不易維護。

設想:將sql中的佔位符及對應的參數類型配置在配置文件中,能夠自動輸入 映射。

 

4、遍歷查詢結果集存在硬編碼(列名)。

設想:自動進行sql查詢結果向java對象的映射(輸出映射)。

 

3       mybatis架構(重點)

3.1     mybatis介紹

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名爲MyBatis,實質上Mybatis對ibatis進行一些改進。

目前mybatis在github上託管。git(分佈式版本控制,當前比較流程)

 

MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,

使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。

Mybatis通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,

並通過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。

 

 

3.2     mybatis架構

 

 

 4       mybatis入門程序

4.1     需求

         實現用戶查詢:

                   根據用戶id(主鍵)查詢用戶信息(單條記錄)

                   根據用戶名稱模糊查詢用戶信息(多條記錄)

         用戶添加

         用戶刪除

         用戶修改

 

4.2     導入jar包

 

從mybatis管網下載(地址:https://github.com/mybatis/mybatis-3/releases)

mybatis-3.2.7.pdf---操作手冊

mybatis-3.2.7.jar--核心 jar包

依賴的jar包

 

4.3     工程結構

 

 

 

4.4     log4j.properties(公用文件)

# Global logging configuration,建議開發環境中要用debug

log4j.rootLogger=DEBUG, stdout

# Console output...

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

 

4.5     SqlMapConfig.xml(公用文件)

通過SqlMapConfig.xml加載mybatis運行環境。

 

 

4.6     根據id查詢用戶

 

4.6.1     pojo(User.java)

 

 

4.6.2     User.xml(重點)

建議命名規則:表名+mapper.xml

早期ibatis命名規則:表名.xml

 

 

4.6.3     編碼

創建SqlSessionFactory:

 

 

 

4.7     根據用戶名稱模糊查詢用戶信息

根據用戶名稱模糊查詢用戶信息可能返回多條記錄。

4.7.1     User.xml

建議命名規則:表名+mapper.xml

早期ibatis命名規則:表名.xml

4.7.2     編碼

 

 

4.7.3     使用${}接收參數

 

4.8     mybatis開發過程小結

1、編寫SqlMapConfig.xml

2、編寫mapper.xml

         定義了statement

3、編程通過配置文件創建SqlSessionFactory

4、通過SqlSessionFactory獲取SqlSession

5、通過SqlSession操作數據庫

         如果執行添加、更新、刪除需要調用SqlSession.commit()

6、SqlSesion使用完成要關閉

 

4.9     用戶添加

向用戶表插入一條記錄。

 

4.9.1     User.xml

 

 

 

4.9.2     編碼

 

 

 

4.9.3     主鍵返回

需求:user對象插入到數據庫後,新記錄的主鍵要通過user對象返回,通過user獲取主鍵值。

 

解決思路:

通過LAST_INSERT_ID()獲取剛插入記錄的自增主鍵值,在insert語句執行後,執行select LAST_INSERT_ID()就可以獲取自增主鍵。

 

User.xml修改:

   

 

使用mysql的uuid機制生成主鍵:

 

使用uuid生成主鍵的好處是不考慮數據庫移植後主鍵衝突問題。

 

實現思路:

先查詢uuid得到主鍵,將主鍵設置到user對象中,將user對象插入數據庫。

 

 

 

實現 oracle數據庫主鍵返回,如何做??

oracle沒有自增主鍵機制,使用序列完成主鍵生成。

 

實現思路:

先查詢序列得到主鍵,將主鍵設置到user對象中,將user對象插入數據庫。

 

 

 

4.10        用戶刪除和更新

 

 

 

4.10.1              編碼

 

// 測試根據id刪除用戶(得到單條記錄)

   @Test

   public void testDeleteUser() {

 

      // 通過sqlSessionFactory創建sqlSession

 

      SqlSession sqlSession = sqlSessionFactory.openSession();

 

      // 通過sqlSession操作數據庫

      try {

         sqlSession.delete("test.deleteUser", 35);

         // 需要提交事務

         sqlSession.commit();

 

      } catch (Exception e) {

         e.printStackTrace();

      } finally {

         // 關閉sqlSession

         sqlSession.close();

      }

 

 

   }

 

   // 測試根據id更新用戶(得到單條記錄)

   @Test

   public void testUpdateUser() {

 

      // 通過sqlSessionFactory創建sqlSession

 

      SqlSession sqlSession = sqlSessionFactory.openSession();

 

      // 通過sqlSession操作數據庫

      // 創建更新數據對象,要求必須包括 id

      User user = new User();

      user.setId(35);

      user.setUsername("燕青");

      user.setAddress("河南鄭州");

//    user.setBirthday(new Date());

      user.setSex("1");

 

      try {

         sqlSession.update("test.updateUser", user);

         // 需要提交事務

         sqlSession.commit();

 

      } catch (Exception e) {

         e.printStackTrace();

      } finally {

         // 關閉sqlSession

         sqlSession.close();

      }

 

      System.out.println("用戶的id=" + user.getId());

 

   }

 

 

4.11        Mybatis解決jdbc編程的問題

1、  數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。

解決:在SqlMapConfig.xml中配置數據鏈接池,使用連接池管理數據庫鏈接。

2、  Sql語句寫在代碼中造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。

解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。

3、  向sql語句傳參數麻煩,因爲sql語句的where條件不一定,可能多也可能少,佔位符需要和參數一一對應。

解決:Mybatis自動將java對象映射至sql語句,通過statement中的parameterType定義輸入參數的類型。

4、  對結果集解析麻煩,sql變化導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。

解決:Mybatis自動將sql執行結果映射至java對象,通過statement中的resultType定義輸出結果的類型。

 

 

4.12        mybatis與hibernate重要區別

企業開發進行技術選型 ,考慮mybatis與hibernate適用場景。

 

mybatis:入門簡單,程序容易上手開發,節省開發成本 。mybatis需要程序員自己編寫sql語句,是一個不完全 的ORM框架,對sql修改和優化非常容易實現 。

mybatis適合開發需求變更頻繁的系統,比如:互聯網項目。

 

hibernate:入門門檻高,如果用hibernate寫出高性能的程序不容易實現。hibernate不用寫sql語句,是一個 ORM框架。

hibernate適合需求固定,對象數據模型穩定,中小型項目,比如:企業OA系統。

 

總之,企業在技術選型時根據項目實際情況,以降低成本和提高系統 可維護性爲出發點進行技術選型。

 

 

 

 

4.13        總結

 

4.13.1              SqlMapConfig.xml

是mybatis全局配置文件,只有一個,名稱不固定的,主要mapper.xml,mapper.xml中配置 sql語句

 

4.13.2              mapper.xml

mapper.xml是以statement爲單位進行配置。(把一個sql稱爲一個statement),satatement中配置 sql語句、parameterType輸入參數類型(完成輸入映射)、resultType輸出結果類型(完成輸出映射)。

 

還提供了parameterMap配置輸入參數類型(過期了,不推薦使用了)

還提供resultMap配置輸出結果類型(完成輸出映射),明天重點講通過resultMap完成複雜數據類型的映射(一對多,多對多映射)

 

 

4.13.3   #{}

表示一個佔位符,向佔位符輸入參數,mybatis自動進行java類型和jdbc類型的轉換。

程序員不需要考慮參數的類型,比如:傳入字符串,mybatis最終拼接好的sql就是參數兩邊加單引號。

#{}接收pojo數據,可以使用OGNL解析出pojo的屬性值

4.13.4    ${}

表示sql的拼接,通過${}接收參數,將參數的內容不加任何修飾拼接在sql中。

${}也可以接收pojo數據,可以使用OGNL解析出pojo的屬性值

缺點:不能防止sql注入。

 

 

4.13.5              selectOne

用於查詢單條記錄,不能用於查詢多條記錄,否則異常:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

 

 

4.14        selectList

用於查詢多條記錄,可以用於查詢單條記錄的。

 

 

5       mybatis開發dao的方法

5.1     SqlSession作用範圍

是使用局部變量、成員變量。。。。???

 

5.1.1     SqlSessionFactoryBuilder

         SqlSessionFactoryBuilder是以工具類方式來使用,需要創建sqlSessionFactory就new一個SqlSessionFactoryBuilder。

 

5.1.2     sqlSessionFactory

         正常開發時,以單例方式管理sqlSessionFactory,整個系統運行過程中sqlSessionFactory只有一個實例,將來和spring整合後由spring以單例方式管理sqlSessionFactory。

 

 

5.1.3     SqlSession

 

sqlSession是一個面向用戶(程序員)的接口,程序員調用sqlSession的接口方法進行操作數據庫。

sqlSession能否以單例 方式使用??

由於sqlSession是線程不安全,所以sqlSession最佳應用範圍在方法體內,在方法體內定義局部變量使用sqlSession。

 

 

 

 

5.2     原始dao開發方式

程序員需要寫dao接口和dao 的實現 類

 

5.2.1     dao接口

 

5.2.2     dao接口實現

 

 

5.2.3     測試代碼

 

 

 

 

 

 

5.3     mapper代理的方式

程序員只需要寫dao接口,dao接口實現對象由mybatis自動生成代理對象。

本身dao在三層架構中就是一個通用的接口。

 

 

5.3.1     上邊原始dao開發方式的問題

1 dao的實現類中存在重複代碼,整個mybatis操作的過程代碼模板重複(先創建sqlsession、調用sqlsession的方法、關閉sqlsession)

 

2、dao的實現 類中存在硬編碼,調用sqlsession方法時將statement的id硬編碼。

 

5.3.2     mapper開發規範

 

要想讓mybatis自動創建dao接口實現類的代理對象,必須遵循一些規則:

 

1、mapper.xml中namespace指定爲mapper接口的全限定名

 

此步驟目的:通過mapper.xml和mapper.java進行關聯。

 

2、mapper.xml中statement的id就是mapper.java中方法名

 

3、mapper.xml中statement的parameterType和mapper.java中方法輸入參數類型一致

 

4、mapper.xml中statement的resultType和mapper.java中方法返回值類型一致.

 

 

 

 

5.3.3     mapper.xml(映射文件)

mapper映射文件的命名方式建議:表名Mapper.xml

 

namespace指定爲mapper接口的全限定名

 

 

 

5.3.4     mapper接口

mybatis提出了mapper接口,相當 於dao 接口。

 

mapper接口的命名方式建議:表名Mapper

 

 

 

5.3.5     將mapper.xml在SqlMapConfig.xml中加載

 

 

5.3.6     mapper接口返回單個對象和集合對象

不管查詢記錄是單條還是多條,在 statement中resultType定義一致,都是單條記錄映射的pojo類型。

mapper接口方法返回值,如果是返回的單個對象,返回值類型是pojo類型,生成的代理對象內部通過selectOne獲取記錄,如果返回值類型是集合對象,生成的代理對象內部通過selectList獲取記錄。

 

 

 

 

 

5.3.7     問題

5.3.7.1              返回值的問題

如果方法調用的statement,返回是多條記錄,而mapper.java方法的返回值爲pojo,此時代理對象通過selectOne調用,由於返回多條記錄,所以報錯:

 

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

        

5.3.7.2              輸入參數的問題

使用mapper代理的方式開發,mapper接口方法輸入 參數只有一個,可擴展性是否很差??

 

可擴展性沒有問題,因爲dao層就是通用的,可以通過擴展pojo(定義pojo包裝類型)將不同的參數(可以是pojo也可以簡單類型)傳入進去。

 

 

6       sqlMapConfig.xml

 

SqlMapConfig.xml中配置的內容和順序如下:

 

properties(屬性)

settings(全局配置參數)

typeAliases(類型別名)

typeHandlers(類型處理器)

objectFactory(對象工廠)

plugins(插件)

environments(環境集合屬性對象)

environment(環境子屬性對象)

transactionManager(事務管理)

dataSource(數據源)

mappers(映射器)

 

6.1     properties屬性定義

 可以把一些通用的屬性值配置在屬性文件中,加載到mybatis運行環境內。

比如:創建db.properties配置數據庫連接參數。

 

 

 

 

注意: MyBatis 將按照下面的順序來加載屬性:

u  在 properties 元素體內定義的屬性首先被讀取。

u  然後會讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。

u  最後讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性。

 

建議使用properties,不要在properties中定義屬性,只引用定義的properties文件中屬性,並且properties文件中定義的key要有一些特殊的規則。

 

6.2     settings全局參數配置

mybatis運行時可以調整一些全局參數(相當於軟件的運行參數),參考:mybatis-settings.xlsx

根據使用需求進行參數配置。

注意:小心配置,配置參數會影響mybatis的執行。

 

ibatis的全局配置參數中包括很多的性能參數(最大線程數,最大待時間。。。),通過調整這些性能參數使ibatis達到高性能的運行,mybatis沒有這些性能參數,由mybatis自動調節。

 

6.3     typeAliases(常用)

 

可以將parameterType、resultType中指定的類型 通過別名引用。

 

6.3.1     mybaits提供了很多別名

別名

映射的類型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

 

6.3.2     自定義別名

 

 

 

 

6.3.3     使用別名

在parameterType、resultType中使用別名:

 

 

6.3.4     typeHandlers

 

類型處理器將java類型和jdbc類型進行映射。

 

mybatis默認提供很多類型處理器,一般情況下夠用了。

 

6.3.5     mappers

 

 

 

7       輸入和輸出映射

通過parameterType完成輸入映射,通過resultType和resultMap完成輸出映射。

 

7.1     parameterType傳遞pojo包裝對象

可以定義pojo包裝類型擴展mapper接口輸入參數的內容。

 

需求:

自定義查詢條件查詢用戶信息,需要向statement輸入查詢條件,查詢條件可以有user信息、商品信息。。。。

 

7.1.1     包裝類型

 

 

7.1.2     mapper.xml

 

 

 

7.1.3     mapper.java

 

 

7.1.4     測試

 

 

 

7.1.5     異常

如果parameterType中指定屬性錯誤,異常,找不到getter方法:

 

org.apache.ibatis.exceptions.PersistenceException:

### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'userCusto' in 'class cn.itcast.mybatis.po.UserQueryVo'

### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'userCusto' in 'class cn.itcast.mybatis.po.UserQueryVo'

        

 

注意:如果將來和spring整合後,不是通過調用getter方法來獲取屬性值,通過反射強讀取pojo的屬性值。

 

7.2     resultType

指定輸出結果的類型(pojo、簡單類型、hashmap..),將sql查詢結果映射爲java對象 。

 

7.2.1     返回簡單類型

mapper.xml

 

 

mapper.java

 

 

 

 

 

注意:

如果查詢記錄結果集爲一條記錄且一列再使用返回簡單類型。

 

7.3     resultMap(入門)

resultType :指定輸出結果的類型(pojo、簡單類型、hashmap..),將sql查詢結果映射爲java對象 。

         使用resultType注意:sql查詢的列名要和resultType指定pojo的屬性名相同,指定相同 屬性方可映射成功,如果sql查詢的列名要和resultType指定pojo的屬性名全部不相同,list中無法創建pojo對象的。

 

resultMap:將sql查詢結果映射爲java對象。

         如果sql查詢列名和最終要映射的pojo的屬性名不一致,使用resultMap將列名和pojo的屬性名做一個對應關係 (列名和屬性名映射配置)

 

 

7.3.1     resultMap配置

 

 

 

7.3.2     使用resultMap

 

 

7.3.3     mapper.java

 

 

 

 

 

8       動態sql(重點)

mybatis重點是對sql的靈活解析和處理。

 

8.1     需求

將自定義查詢條件查詢用戶列表和查詢用戶列表總記錄數改爲動態sql

 

8.2     if和where

 

 

 

8.3     sql片段

通過sql片段可以將通用的sql語句抽取出來,單獨定義,在其它的statement中可以引用sql片段。

通用的sql語句,常用:where條件、查詢列

 

8.3.1     sql片段的定義

 

 

8.3.2     引用sql片段

 

 

 

8.4     foreach

 

在statement通過foreach遍歷parameterType中的集合類型。

 

需求:

根據多個用戶id查詢用戶信息。

 

 

8.4.1     在userQueryVo中定義list<Integer> ids

 

在userQueryvo中定義list<Integer> ids存儲多個id

 

 

 

8.4.2     修改where語句

 

使用foreach遍歷list:

 

 

 

8.4.3     測試代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章