數據庫連接池
當一個連接通道使用完後,系統並不會將其釋放,而是將它存儲在連接池裏。下次需要使用連接通道的時候,系統會判斷連接池裏是否有空閒的連接通道對象。如果有,設置其連接字符串,修改其連接狀態,重新使用。
這樣能在很大程度上減少實例化的次數,節省了內存和時間,提升了效率。
mybatis連接池提供了3種方式的配置:
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource標籤,type屬性就是表示採用何種連接池方式。
type屬性的取值:
POOLED 使用連接池。採用傳統的javax.sql.DataSource規範中的連接池,mybatis中有針對規範的實現
UNPOOLED 不使用連接池。採用傳統的獲取連接的方式,雖然也實現Javax.sql.DataSource接口,但是並沒有使用池的思想。
JNDI 採用服務器提供的JNDI技術實現,來獲取DataSource對象,不同的服務器所能拿到DataSource是不一樣。
MyBatis中的事務
什麼是事務
是數據庫操作的最小工作單元,是作爲單個邏輯工作單元執行的一系列操作;這些操作作爲一個整體一起向系統提交,要麼都執行、要麼都不執行;事務是一組不可再分割的操作集合。
事務的四大特性(ACID)
1 、原子性
事務是數據庫的邏輯工作單位,事務中包含的各操作要麼都做,要麼都不做
2 、一致性
事 務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。因此當數據庫只包含成功事務提交的結果時,就說數據庫處於一致性狀態。如果數據庫系統 運行中發生故障,有些事務尚未完成就被迫中斷,這些未完成事務對數據庫所做的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是 不一致的狀態。
3 、隔離性
一個事務的執行不能其它事務干擾。即一個事務內部的操作及使用的數據對其它併發事務是隔離的,併發執行的各個事務之間不能互相干擾。
4 、持續性
也稱永久性,指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。
不考慮事務隔離性會產生的三大問題
髒讀:指當一個事務正字訪問數據,並且對數據進行了修改,而這種數據還沒有提交到數據庫中,這時,另外一個事務也訪問這個數據,然後使用了這個數據。因爲這個數據還沒有提交那麼另外一個事務讀取到的這個數據我們稱之爲髒數據。依據髒數據所做的操作肯能是不正確的。
不可重複讀:指在一個事務內,多次讀同一數據。在這個事務還沒有執行結束,另外一個事務也訪問該同一數據,那麼在第一個事務中的兩次讀取數據之間,由於第二個事務的修改第一個事務兩次讀到的數據可能是不一樣的,這樣就發生了在一個事物內兩次連續讀到的數據是不一樣的,這種情況被稱爲是不可重複讀。
幻象讀:一個事務先後讀取一個範圍的記錄,但兩次讀取的紀錄數不同,我們稱之爲幻象讀(兩次執行同一條 select 語句會出現不同的結果,第二次讀會增加一數據行,並沒有說這兩次執行是在同一個事務中)
Mybatis中事務的提交方式,本質上就是調用JDBC的setAutoCommit()來實現事務控制。
動態SQL
常用的動態SQL元素包括:
- if
- where
- set
- foreach
- choose
<if>標籤
動態SQL通常會做的事情就是有條件的包含where子句的一部分:
<!--使用if語句-->
<select id="findUserByCondition" resultType="com.lwl.domain.User" parameterType="user">
select * from user where sex = '男';
<!--可選條件,如果傳入的參數中username爲null,就將查詢條件加上username名-->
<if test="username != null">
and username = #{username};
</if>
</select>
以上如果傳入的user實例中username爲空就查詢所有姓名爲男的信息,如果不爲空,就查詢性別爲男並且username爲傳入user實例中的username的信息。
如果要傳入的條件有多個:
<!--使用if語句-->
<select id="findUserByCondition" resultType="com.lwl.domain.User" parameterType="user">
select * from user
<where>
<if test="username != null">
and username = #{username};
</if>
<if test="sex != null">
and sex = #{sex};
</if>
</where>
</select>
<where>標籤
下面這段是根據傳入user實例的username查詢改用戶的信息,如果傳入的username是空的話,返回的結果是select * from user查詢所有用戶的信息。
<!--使用if語句-->
<select id="findUserByCondition" resultType="com.lwl.domain.User" parameterType="user">
select * from user
<where>
<if test="username != null">
username = #{username};
</if>
</where>
</select>
<set>標籤
set元素可以用於動態包含需要更新的列,而捨去其它的。
動態的更新員工的地址:
<!--修改用戶-->
<update id="updateUser" parameterType="User">
update user
<set>
<if test="address != null">
address=#{address}
</if>
</set>
where id =#{id};
</update>
<foreach>標籤
對一個集合進行便利的時候需要使用,通常發生在構建IN條件語句中:
<!--使用queryVo中的Id集合實現查詢用戶列表-->
<select id="findUserByIds" resultType="com.lwl.domain.User" parameterType="com.lwl.domain.QueryVo">
select * from user
<where>
<if test="ids != null and ids.size>0" >
<foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
collection爲要遍歷的集合,open爲拼接字符串的開始,close爲拼接字符串的結束,separator爲迭代中間放置的分隔符。
<choose>標籤
有時候不想使用所有的條件語句,而是準備二選一,可以使用choose標籤,類似於switch語句。
<!--使用if語句-->
<select id="findUserByCondition" resultType="com.lwl.domain.User" parameterType="user">
select * from user where sex = '男'
<choose>
<when test="username != null">
and username = #{username};
</when>
<when test="address != null">
and address = #{address};
</when>
</choose>
</select>