框架學習系列 mybatis 第一篇 原生jdbc連接分析
本節主要內容
1:mybatis的介紹
2:原始jdbc問題分析
3:JDBC演變成mybatis的過程
4:總結&下節預告
本文是《凱哥陪你學系列-框架學習之mybatis框架學習》中第一篇 mybatis簡介&原生jdbc連接分析
聲明:本文系凱哥原創。轉載請註明出處
一:mybatis的介紹
1.1:mybatis是什麼?
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis,實質上Mybatis對ibatis進行一些改進。
MyBatis是一個優秀的持久層框架,它對jdbc的操作資料庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。
Mybatis通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。
與hibernate都屬於是ORM框架。但是具體的說,hibernate是一個完全的ORM框架,二mybatis是一個不完全的orm框架。
mybatis讓程序開發者只關注sql本事,而不需要關注如何連接的創建、statement的創建等操作。
mybatis會將輸入參數、輸出結果進行映射。
二:分析原生JDBC程序中存在的問題
2.1:原生jdbc程序代碼
2.1.1 資料庫腳本。
1:創建mybatis這個資料庫。腳本:
2:使用剛創建的mybatis這個資料庫
3:創建用戶(user)這個表。欄位有 id/nam/gender/age
腳本如下:
初始化三條數據:
2.2 jdbc連接資料庫及查詢步驟
1:引入所需要的jar(mysql的)
2:使用java程序連接mysql資料庫步驟
a:獲取載入資料庫的驅動
b:通過驅動管理類獲取資料庫連接
其中包括資料庫地址、用戶名、密碼
說明:
設置資料庫連接地址、連接的庫名及使用編碼:jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
資料庫用戶名:root
資料庫密碼為:123456
c:定義sql語句使用?表示佔位符
d:獲取預處理的statement
e:設置參數、第一個參數為sql語句中參數的序號(?的位置。從1開始的),第二個參數為設置的參數值
f:向資料庫發送sql執行查詢。查詢結果集
g:遍歷查詢結果集
h:釋放資源
執行完成後控制台輸出為:
完整代碼:
2.3:使用原生jdbc的問題
1:在創建連接的時候,存在硬編碼(數據非動態的)
對應程序中:
資料庫連接、用戶名、密碼都是在程序中寫死的。
解決方案:
可以將這些信息存放在全局的配置文件中
2:在執行statement的時候存在硬編碼
對應程序中:
我們可以看到,這裡查詢學在程序中,是固定的。
解決方案:
sql卸載配置文件(映射文件中)
3:頻繁的開啟和關閉資料庫連接,會造成資料庫性能的下降
對應程序中:
解決方案:
使用資料庫連接池(全局配置文件)
三: JDBC演變到Mybatis過程
上面我們看到了實現JDBC有七個步驟,哪些步驟是可以進一步封裝的,減少我們開發的代碼量。
3.1 第一步優化:連接獲取和釋放
問題描述:
資料庫連接頻繁的開啟和關閉本身就造成了資源的浪費,影響系統的性能。
解決問題:
資料庫連接的獲取和關閉我們可以使用資料庫連接池來解決資源浪費的問題。通過連接池就可以反覆利用已經建立的連接去訪問資料庫了。減少連接的開啟和關閉的時間。
問題描述:
但是現在連接池多種多樣,可能存在變化,有可能採用DBCP的連接池,也有可能採用容器本身的JNDI資料庫連接池。
解決問題:
我們可以通過DataSource進行隔離解耦,我們統一從DataSource裡面獲取資料庫連接,DataSource具體由DBCP實現還是由容器的JNDI實現都可以,所以我們將DataSource的具體實現通過讓用戶配置來應對變化。
3.2 第二步優化:SQL統一存取
問題描述:
我們使用JDBC進行操作資料庫時,SQL語句基本都散落在各個JAVA類中,這樣有三個不足之處:
第一,可讀性很差,不利於維護以及做性能調優。
第二,改動Java代碼需要重新編譯、打包部署。
第三,不利於取出SQL在資料庫客戶端執行(取出後還得刪掉中間的Java代碼,編寫好的SQL語句寫好後還得通過+號在Java進行拼湊)。
解決問題:
我們可以考慮不把SQL語句寫到Java代碼中,那麼把SQL語句放到哪裡呢?首先需要有一個統一存放的地方,我們可以將這些SQL語句統一集中放到配置文件或者資料庫裡面(以key-value的格式存放)。然後通過SQL語句的key值去獲取對應的SQL語句。
既然我們將SQL語句都統一放在配置文件或者資料庫中,那麼這裡就涉及一個SQL語句的載入問題。
3.3 第三步優化:傳入參數映射和動態SQL
問題描述:
很多情況下,我們都可以通過在SQL語句中設置佔位符來達到使用傳入參數的目的,這種方式本身就有一定局限性,它是按照一定順序傳入參數的,要與佔位符一一匹配。但是,如果我們傳入的參數是不確定的(比如列表查詢,根據用戶填寫的查詢條件不同,傳入查詢的參數也是不同的,有時是一個參數、有時可能是三個參數),那麼我們就得在後台代碼中自己根據請求的傳入參數去拼湊相應的SQL語句,這樣的話還是避免不了在Java代碼裡面寫SQL語句的命運。既然我們已經把SQL語句統一存放在配置文件或者資料庫中了,怎麼做到能夠根據前台傳入參數的不同,動態生成對應的SQL語句呢?
解決問題:
第一,我們先解決這個動態問題,按照我們正常的程序員思維是,通過if和else這類的判斷來進行是最直觀的,這個時候我們想到了JSTL中的這樣的標籤,那麼,能不能將這類的標籤引入到SQL語句中呢?假設可以,那麼我們這裡就需要一個專門的SQL解析器來解析這樣的SQL語句,但是,if判斷的變數來自於哪裡呢?傳入的值本身是可變的,那麼我們得為這個值定義一個不變的變數名稱,而且這個變數名稱必須和對應的值要有對應關係,可以通過這個變數名稱找到對應的值,這個時候我們想到了key-value的Map。解析的時候根據變數名的具體值來判斷。
假如前面可以判斷沒有問題,那麼假如判斷的結果是true,那麼就需要輸出的標籤裡面的SQL片段,但是怎麼解決在標籤裡面使用變數名稱的問題呢?這裡我們需要使用一種有別於SQL的語法來嵌入變數(比如使用#變數名#)。這樣,SQL語句經過解析後就可以動態的生成符合上下文的SQL語句。
還有,怎麼區分開佔位符變數和非佔位變數?有時候我們單單使用佔位符是滿足不了的,佔位符只能為查詢條件佔位,SQL語句其他地方使用不了。這裡我們可以使用#變數名#表示佔位符變數,使用$變數名$表示非佔位符變數。
3.4 第四步優化:結果映射和結果緩存
問題描述:
執行SQL語句、獲取執行結果、對執行結果進行轉換處理、釋放相關資源是一整套下來的。假如是執行查詢語句,那麼執行SQL語句後,返回的是一個ResultSet結果集,這個時候我們就需要將ResultSet對象的數據取出來,不然等到釋放資源時就取不到這些結果信息了。我們從前面的優化來看,以及將獲取連接、設置傳入參數、執行SQL語句、釋放資源這些都封裝起來了,只剩下結果處理這塊還沒有進行封裝,如果能封裝起來,每個資料庫操作都不用自己寫那麼一大堆Java代碼,直接調用一個封裝的方法就可以搞定了。
解決問題:
我們分析一下,一般對執行結果的有哪些處理,有可能將結果不做任何處理就直接返回,也有可能將結果轉換成一個JavaBean對象返回、一個Map返回、一個List返回等`,結果處理可能是多種多樣的。從這裡看,我們必須告訴SQL處理器兩點:第一,需要返回什麼類型的對象;第二,需要返回的對象的數據結構怎麼跟執行的結果映射,這樣才能將具體的值copy到對應的數據結構上。
接下來,我們可以進而考慮對SQL執行結果的緩存來提升性能。緩存數據都是key-value的格式,那麼這個key怎麼來呢?怎麼保證唯一呢?即使同一條SQL語句幾次訪問的過程中由於傳入參數的不同,得到的執行SQL語句也是不同的。那麼緩存起來的時候是多對。但是SQL語句和傳入參數兩部分合起來可以作為數據緩存的key值。
3.5 第五步優化:解決重複SQL語句問題
問題描述:
由於我們將所有SQL語句都放到配置文件中,這個時候會遇到一個SQL重複的問題,幾個功能的SQL語句其實都差不多,有些可能是SELECT後面那段不同、有些可能是WHERE語句不同。有時候表結構改了,那麼我們就需要改多個地方,不利於維護。
解決問題:
當我們的代碼程序出現重複代碼時怎麼辦?將重複的代碼抽離出來成為獨立的一個類,然後在各個需要使用的地方進行引用。對於SQL重複的問題,我們也可以採用這種方式,通過將SQL片段模塊化,將重複的SQL片段獨立成一個SQL塊,然後在各個SQL語句引用重複的SQL塊,這樣需要修改時只需要修改一處即可。
四:總結&下節預告
通過本節學習我們需要掌握的
1:jdbc怎麼連接資料庫進行操作的
下節預告: 我們知道jdbc連接資料庫的步驟(原理),那麼mybatis的工作原理又是什麼呢?
歡迎學習下一節:《 mybatis 第二篇 mybatis的工作原理》
※從零學java筆錄-第43篇第二階段封裝private關鍵字
※從零學java筆錄-第42篇第二階段成員變數和局部變數的區別
※從零學java筆錄-第41篇 基礎第二階段 3類的定義及使用
※從零學java筆錄-第40篇第二階段面向對象 類與對象的概述
※從零學java筆錄-第39篇1 面向對象思想及概述
TAG:凱哥java |
※mysql字元串連接concat和concat ws函數
※springboot項目中使用原生jdbc連接MySQL資料庫
※python後台架構Django——連接讀寫mysql資料庫
※springboot配置druid連接池
※ajax,long poll,websocket連接的區別原理
※python web開發-flask連接sqlite資料庫
※Memcached 連接
※未能連接「can』t contact with the world」
※HikariCP源碼分析之leakDetectionThreshold及實戰解決Spark/Scala連接池泄漏
※nodejs連接mongodb,對數據增刪改查操作(跳過坑)Windows版
※Canonical發布信息圖:Ubuntu Linux連接一切
※Steam連接任天堂switch pro手柄圖文教程
※thinkphp5連接oracle資料庫
※Molex 升級PicoBlade 連接器系統
※配置SAP Solution Manager連接監控遠程Microsoft SQL Server
※詳解node + mongoDb(mongoDb安裝、運行,在node中連接增刪改查)
※Kickstarter 推出 Switch 連接藍芽音頻設備
※Amphenol Industrial高電流、低溫升 Amphe-PD系列連接器在貿澤開售
※TE Connectivity推出124位Sliver連接器和電纜組件
※ARM收購物聯網連接專業公司Stream Technologies