mybatis----基礎
基礎知識
- 安裝
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
對原生態jdbc程式中問題總結
- 環境
java環境:jdk
- jdbc程式
使用jdbc查詢mysql資料庫中使用者表的記錄
- 問題總結
- 資料庫連線、使用時建立、不使用時就立即釋放,對資料庫進行頻繁連線開啟和關閉,造成資料庫資源浪費,影響資料庫效能(使用連線池管理資料庫來連線進行優化)
- 將sql語句硬編碼到Java程式碼中,如果sql語句修改,需要重新編譯程式碼,不利於系統維護(將sql語句配置在xml配置檔案中,即使sql變化,也不需要對java程式碼進行重新編譯)
- 向preparedStatement中設定引數,對佔位符號位置和設定引數值,硬編碼在Java程式碼中,不利於系統維護(將sql語句及佔位符號和引數全部配置在xml中)
- 從resultSet中遍歷結果集資料時,存在硬編碼,將獲取表的欄位進行硬編碼,不利於系統維護(將查詢的結果集,自動對映成java物件。)
mybatis是什麼
mybatis是一個持久層框架,是apache下的頂級專案。
mybatis是讓程式設計師將主要精力放在sql上,通過mybatis提供的對映方式,自由靈活的生成(半自動化,大部分需要程式設計師編寫sql)滿足需要的sql語句
mybatis可以將向preparedStatement中的輸入引數自動進行輸入對映,將查詢結果集靈活對映成java物件(輸出對映)
mybatis框架
SqlMapConfig.xml 是mybatis的全域性配置檔案,配置了資料來源、事務等mybatis執行環境(第三方軟體進行配置)
mybatis自己還需要配置對映檔案(mapper.xml、mapper.xml、mapper.xml……【對映檔案】)也就是配置sql語句
SqlSessionFactory(會話工廠),根據配置檔案建立工廠
作用:建立SqlSession
SqlSession(會話),是一個介面,面向使用者(程式設計師)的介面
作用:運算元據庫(發出增、刪、改、查)
Executor(執行器),也是一個介面(基本執行器、快取執行器)
作用:運算元據庫(發出增、刪、改、查)
mapped statement(底層封裝物件)
作用:對運算元據庫儲存封裝,包括sql語句,輸入引數、輸出結果型別
入門程式
- 編寫
log4j.properties
進行日誌輸出
# Global logging configuration
#在開發環境下日誌級別要設定成DEBUG,生成環境設定成info或ERROR
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 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
- 編寫全域性配置
SqlMapConfig.xml
- 對映檔案
- 對映檔案命名
User.xml(原始mybatis命名),mapper代理開發對映檔案叫xxxMapper.xml,比如:UserMapper.xml
在對映檔案中配置sql語句
#{}與${}
- #{} 表示一個佔位符,#{}接受輸入引數,型別可以是簡單的型別,pojo、hashmap。
如果接受簡單型別,#{}中可以寫成value或其他名稱
#{}接受pojo物件值,通過OGNL讀取物件中的屬性值,通過屬性。屬性。屬性……的方式獲取物件屬性值 - ${} 表示一個拼接符號,會引起sql注入,所以不建議使用
${}接受輸入引數,型別可以是簡單的型別,pojo、hashmap。
如果接受簡單型別,${}中只可以寫成value
parameterType、resuletType
parameterType : 指定輸入引數的型別
resuletType : 指定輸出引數的型別
自增主鍵返回
mysql自增主鍵,執行insert提交之前自動生成一個自增主鍵。
通過mysql函式獲取到剛插入記錄的自增主鍵:LAST_INSERT_ID()
是在insert之後呼叫此函式,需要修改UserInsert的定義
<insert id=“insertUser” parameter="cn.persist.entily.User">
<!--
將插入資料的主鍵返回,返回到user物件中
SELECT LAST_INSERT_ID():得到剛insert進去的記錄的主鍵的值,只適用於自增主鍵
KeyProperty:將查詢到的主鍵值parameterType指定的物件的哪個屬性
order:SELECT LAST_INSERT_ID()執行順序,相對於insert語句來說它的執行順序
resultType:指定SELECT LAST_INSERT_ID()的結果型別
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Inteager">
SELECT LAST_INSERT_ID()
</selectKey>
<!--
username,password,address是資料表中的對應的欄位名稱
#{username},#{password},#{address}是實體類中對應的屬性名
-->
INSERT into user(username,password,address) value(#{username},#{password},#{address})
</insert>
非自增主鍵返回(使用uuid)
使用mysql的uuid()函式生成主鍵,需要修改表中id欄位型別為string,長度設定成35位
執行思路:
先通過uuid()查詢到主鍵,將主鍵輸入到sql語句中
執行uuid()語句順序相對於insert語句之前執行
<insert id=“insertUser” parameter="cn.persist.entily.User">
<!--
使用mysql的uuid()生成主鍵
執行過程:
首先通過uuid()得到主鍵,將主鍵設定到user物件的id屬性中
其次在insert執行時,從user物件中取出id屬性值
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
<!--
id,username,password,address是資料表中的對應的欄位名稱
#{id},#{username},#{password},#{address}是實體類中對應的屬性名
-->
INSERT into user(id,username,password,address) value(#{id},#{username},#{password},#{address})
</insert>
mybatis開發dao的方法
- sqlSession使用範圍
- sqlSessionFactoryBuilder
通過sqlSessionFactoryBuilder建立會話工廠sqlSessionFactory - sqlSessionFactory
通過sqlSessionFactory建立sqlSession,通過單例模式管理sqlSessionFactory(工廠一旦建立,一直使用一個例項) - sqlSession
是一個面向使用者的介面(程式設計師)的介面
sqlSession中提供了很多運算元據庫的方法:例如:selectOne(返回單個物件)selectList(返回單個或多個物件)
sqlSession是執行緒不安全的,在sqlSession實現類中除了有介面中的方法(運算元據庫的方法)還有資料域屬性
sqlSession最佳應用場合在方法體內,定義為區域性變數使用
- sqlSessionFactoryBuilder
原始dao開發方法(程式設計師需要寫dao介面和dao實現類)
- 思路:
程式設計師需要寫dao介面和dao實現類。
需要向dao實現類中注入sqlSessionFactory(會話工廠),在方法體內通過工廠(sqlSessionFactory)建立sqlSession
- 總結原始開發dao的問題
1.dao的介面實現類方法中存在大量模板方法,設想能否將這些程式碼提取出來
2.呼叫sqlSession方法時將statement的id硬編碼了
3.呼叫sqlSession方法時傳入的變數,由於sqlSession方法使用泛型,即使變數型別傳入錯誤,在編譯階段也不報錯,只有在執行時報錯,不利於程式開發
mapper代理方法(程式設計師只需要mapper介面(相當於dao介面))
- 思路
1.程式設計師只需要mapper介面(相當於dao介面),需要遵循一些開發規範,mybatis可以自動生成mapper介面實現類的代理物件
2.程式設計師還需要編寫mapper.xml對映檔案
-
開發規範:
1.在mapper.xml中namespace等於mapper介面地址2.mapper.java介面中的方法名和mapper.xml中statement的id一致
3.mapper.java介面中的方法輸入引數型別和mapper.xml中statement的parameterType指定的型別一致
4.mapper.java介面中的方法返回值型別和mapper.xml中statement的resultType指定的型別一致
總結
以上開發規範主要是對下邊的程式碼進行統一的生成:
SqlMapConfig.xml
- properties(屬性)
需求:
將資料庫連線的引數單獨配置在db.properties
中,只需要在sqlMapConfig.xml
中載入db.properties
的屬性值
在SqlMapConfig.xml
中就不需要對資料庫連線引數硬編碼
將資料庫連線引數只配置在db.properties
中,原因:方便對引數進行統一的管理,其他xml可以引用該db.properties
db.properties
的檔案
sqlMapConfig.xml
載入屬性名稱
建議:
不要在properties元素體內新增任何屬性值,只將屬性值定義在properties檔案中
- setting(全域性配置引數)需要時設定,不需要就不要設定(會影響mybatis的執行)
mybatis框架在執行時可以調整一些執行引數
比如:開啟二級快取、開啟延時載入……
全域性引數將會影響mybatis的執行行為
-
typeAliases(型別別名)
-
單個定義別名
-
批量定義別名
-
在dao.xml中的返回值型別填實體類的名稱,首字母大寫小寫都可以
- typeHandles(型別處理器)
在mybatis中通過typeHandles完成jdbc型別和java型別的轉換
- objectFactory(物件工廠)
- plugins(外掛)
- environments(環境集合屬性物件)
- environment(環境子屬性物件)
- transactionManager(事務管理)
- dataSource(資料來源)
- environment(環境子屬性物件)
- mappers(對映器)
-
通過resource載入單個對映檔案
- 通過mapper介面載入
-
載入單個對映檔案
-
批量載入對映檔案(建議使用)
-
-
動態sql
- 什麼是動態sql
mybatis核心就是對sql語句進行靈活的操作,通過表示式進行判斷,對sql進行靈活拼接、組裝
- 需求:
使用者資訊總和查詢列表和使用者資訊查詢列表總數這兩個statement的定義使用動態sql
對查詢條件進行判斷,如果輸入引數不為空才能進行查詢條件拼接;例如:
<select id="findUserById" parameterType="User" resultType="user">
select * from user
<!--where 可以自動去掉條件中的第一個and-->
<where>
<if test="userCustom!=null">
<if test="userCustom.usermame!=null and userCustom!=''">
and user.username = #{userCustom.username}
</if>
<if test="userCustom.sex != null and userCustom.sex != ''">
and user.sex = #{userCustom.sex}
</if>
</if>
</where>
</select>
sql片段
- 需求:
將上邊實現的動態sql判斷程式碼塊抽取出來,組成一個sql片段。其他的statement中就可以引用sql片段
- 定義sql片段
<!--定義sql片段
id:sql片段的唯一標識
經驗:是基於表單來定義sql片段可重用性高
在sql片段中不要包括where
-->
<sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.usermame!=null and userCustom!=''">
and user.username = #{userCustom.username}
</if>
<if test="userCustom.sex != null and userCustom.sex != ''">
and user.sex = #{userCustom.sex}
</if>
</if>
</sql>
應用sql片段
<select id="findUserById" parameterType="User" resultType="user">
select * from user
<!--where 可以自動去掉條件中的第一個and-->
<where>
/*應用sql片段*/
<include refid="query_user_where" />
/*在這裡還會引用其他的sql片段*/
</where>
</select>
foreach
向sql傳遞陣列或list,mybatis使用foreach解析
- 需求
在使用者查詢列表和查詢總數的statement中增加多個id輸入查詢
sql語句如下:select * from user where id=1 or id=10 or id=16
或select * from user where id in(1,10,16)
- 在輸入引數型別中新增List<Integer>傳入多個id
private List<Integer> ids
傳入多個id - mapper.xml的配置
在查詢條件中,查詢條件定義成一個sql片段,需要修改sql片段
<!--定義sql片段
id:sql片段的唯一標識
經驗:是基於表單來定義sql片段可重用性高
在sql片段中不要包括where
-->
<sql id="query_user_where">
<if test="ids!=null">
<!--使用foreach遍歷傳入ids
collection:指定輸入物件中集合屬性
item:每次遍歷生成的物件
open:開始遍歷時拼接的串
close:結束遍歷時拼接的串
separator:遍歷的兩個物件中需要拼接的串
-->
<foreach collection="ids" item="user_id" open="and (" close=")" separator="or">
/*每次遍歷需要拼接的串*/
id=#{user_id}
</foreach>
</if>
</sql>
select * from user where id in(1,10,16)
的foreach查詢方法
相關文章
- 【FPGA基礎】Latch基礎FPGA
- Pandas 基礎 (2) - Dataframe 基礎
- 前端基礎之jQuery基礎前端jQuery
- python基礎中的基礎Python
- Java基礎-語法基礎Java
- [今日白學]元件的基礎的基礎的基礎元件
- Java基礎-物件導向基礎Java物件
- Python基礎篇-Python基礎01Python
- scala基礎語法-----Spark基礎Spark
- Python基礎:語法基礎(3)Python
- 【web前端基礎 | JS基礎】物件Web前端JS物件
- 基礎
- Linux基礎學習——檔案基礎Linux
- JavaScript 基礎卷(一):基礎語法JavaScript
- 前端基礎入門四(JavaScript基礎)前端JavaScript
- 測試基礎(四)Jmeter基礎使用JMeter
- c#基礎-基礎-16.stringC#
- Python基礎筆記01-Python基礎Python筆記
- Go 基礎教程--2-基礎知識Go
- Web測試基礎-Html基礎知識WebHTML
- WiFi基礎(六):天線基礎知識WiFi
- Golang 基礎之基礎語法梳理 (三)Golang
- 多執行緒基礎-基礎實現執行緒
- TypeScript基礎TypeScript
- 前端——基礎前端
- iOS 基礎iOS
- webpack基礎Web
- XML基礎XML
- JAVA 基礎Java
- xss基礎
- gdb 基礎
- TypeScript (基礎)TypeScript
- View基礎View
- Spark基礎Spark
- XLForm基礎ORM
- git基礎Git
- Python 基礎 (-)Python
- Django基礎Django