既然已經入”坑“mybatis了,你竟然還想着掙脫,我是不會讓你掙脫的~
當然我有一個算是掙脫的辦法。那就是把它學會、理解透。這樣我們也就不用在坑里一直徘徊,也算得上是一種掙脫吧!
我在上一篇文章(mybatis入“坑”第一步)中對創建一個mybatis項目過程中有過的簡單的解釋,這篇文章對增加mybatis生命周期和更加詳細的配置的說明和解釋以及在配置的可能會遇到的關鍵問題。
一、mybatis作用域與生命周期
如下圖是mybatis簡易的生命周期圖。首先mybatis通過IO流的方式獲取配置文件mybatis.config.xml的信息,然后利用SqlSessionFactoryBuilder創建SqlSessionFactory,而SqlSessionFactory是在一個mybatis中是以單例形式存在的,接着利用SqlSessionFactory生產SqlSession,接着利用SqlSession調用SQL Mapper去處理具體的業務。
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder的作用就是用來創建SqlSessionFactory的,所以創建完成SqlSessionFactory后便可以將其丟棄,所以SqlSessionFactoryBuilder的作用域最好就是在局部方法中。當需要它是可以再次重用,但是不要一直保留。
SqlSessionFactory
SqlSessionFactory被創建成功后,你應該保證它在運行期間一直存在,因為每一個業務都需要同樣的SqlSessionFactory去創建SqlSession。因此 SqlSessionFactory 的最佳作用域是應用作用域。也就是要使SqlSessionFactory在每一個mybatis中都是以單例形式存在的。
SqlSession
SqlSession 的實例不是線程安全的,是不能被共享的,所以作用域最好是在局部方法中。同時對於每一次請求SqlSession,返回一個響應后,應該及時關閉它。
Mapper映射器實例
Mapper映射器接口的實例是從 SqlSession 中獲得的,最好將映射器放在方法作用域內,這樣可以更好的管理。Mapper代表的是一個具體的業務處理,所以當處理完該業務時就可以丟棄。Mapper是隨着SqlSession的關閉而消失廢棄的
二、mybatis關鍵配置詳解
properties屬性
properties標簽:可以動態配置屬性。
可以全部在外部進行配置,如下:
<properties resource="db.properties" />
也可以在通過property標簽一部分在外部進行內部配置另一部分在內部進行配置(如下),增加配置的靈活性。
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
當外部的db.properties文件進行配置之后,在property標簽中又配置一遍后會使用哪一個配置呢?
這就需要考慮優先級的問題,通過方法參數傳遞的屬性具有最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的則是 properties 元素中指定的屬性。這里我們的db.properties文件時通過resource指定的,所以優先級大於properties元素指定的屬性。所以優先使用外部的db.properties文件中的配置。
typeAliases類型別名
配置Mapper.xml的類型別名可以降低書寫冗余的全限定類名。通過對實體類別名的配置,簡化開發人員的書寫的代碼量。比如需要書寫com.wkx.pojo.User的全限定類名,在配置別名后便可以僅僅書寫user。
那么如何去配置類型別名呢?
第一種:通過typeAlias的標簽去配置,這樣需要對每一個實體類進行分別配置。type屬性中為實體類的路徑,alias屬性為別名名稱。
<!--配置別名-->
<typeAliases>
<typeAlias type="com.wkx.pojo.User" alias="user"/>
</typeAliases>
第二種:通過package標簽屬性去配置,name屬性為實體類所在的包路徑。
在無注解的情況下,使用 Bean 的首字母小寫的非限定類名來作為它的別名,比如com.wkx.pojo.User的別名便是user
<!--配置別名-->
<typeAliases>
<package name="com.wkx.pojo"/>
</typeAliases>
在有注解的情況下,使用注釋的別名進行配置。
@Alias("wkx")
public class User {
...
...
}
使用注解后便可以通過注解的內容進行類型配置
<mapper namespace="com.wkx.dao.UserMapper">
<select id="getUser" resultType="wkx">
select * from user
</select>
</mapper>
下面列出關於Java類型內建的類型別名,這里只列出一部分,其他的類型的別名可以依次類推。比如別名為_double,映射類型為double;別名為double,對應映射類型為Double。
別名 | 映射的類型 |
---|---|
_int | int |
_integer | int |
int | Integer |
integer | Integer |
map | Map |
hashMap | HashMap |
environments環境配置
用於配置數據的環境。可配置多個數據庫環境,但是SqlSessionFactory只能選擇一個去使用。如下:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
可以在不同的環境下切換不同的數據環境,只需要修改environments標簽中的default屬性對應不同環境下的id屬性,比如development和test不同的環境。
-
事務管理器(transactionManager)
在mybatis中有兩種不同的事務管理器,即type="JDBC"或者type="MANAGED"
JDBC的事務類型是直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域。
MANAGED的事務類型配置幾乎沒有做什么,從不提交或回滾一個連接,而是讓容器來管理事務的整個生命周期。
-
數據源(dataSource)
主要有三種數據源類型,即type="[UNPOOLED|POOLED|JNDI]"。
UNPOOLED的數據源類型是不使用連接池,每次請求時都會打開和關閉連接,顯然這樣的連接數據源類型效率不高。
POOLED的數據源類型是使用連接池的概念,每次請求可以直接從“池”子里拿出活躍的連接,避免了重復的創建連接,提高效率。
JNDI的數據源類型實現是為了能讓在 EJB 或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然后放置一個 JNDI 上下文的數據源引用。
mappers映射器
定義映射的路徑,告訴mybatis去哪里找對應的語句。我們可以是使用類路徑的資源引用方式(推薦使用):
<!-- 使用相對於類路徑的資源引用 -->
<mappers>
<mapper resource="com/wkx/dao/AuthorMapper.xml"/>
</mappers>
可以通過使用完全限定資源定位符(URL)的方式(方式二):
<!-- 使用完全限定資源定位符(URL) -->
<mappers>
<mapper url="file:///E:/UserMapper.xml"/>
</mappers>
可以通過映射器接口實現類的完全限定類名的方式(方式三):
<!-- 使用映射器接口實現類的完全限定類名 -->
<mappers>
<mapper class="com.wkx.dao.UserMapper"/>
</mappers>
可以包的形式將映射器接口全部注冊為映射器的方式(方式四):
<mappers>
<package name="com.wkx.dao"/>
</mappers>
注意:方式三和方式四使用需要具備兩個條件,一個是接口和Mapper的名稱一致,比如UserMapper.java接口和UserMapper.xml必須都是UserMapper,也就是一致的。另一個是接口和Mapper的包名一致。