MyBatis 最關鍵的組成部分是 SqlSessionFactory,我們可以從中獲取 SqlSession,并執行映射的 SQL 語句。SqlSessionFactory 對象可以通過基于 XML 的配置信息或者 Java API 創建。
?
1 mybatis環境,environments 配置默認的數據庫環境
MyBatis 支持配置多個 dataSource 環境,可以將應用部署到不同的環境上,如 DEV(開發環境),TEST(測試換將),QA(質量評估環境),UAT(用戶驗收環境),PRODUCTION(生產環境),可以通過將默認 environment 值設置成想要的environment id 值。
?
2 每個environment 環境配置,需要有dataSource 和?transactionManager
dataSource 元素被用來配置數據庫連接屬性。典型配置如下
<dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource>
?
2.1 dataSource 的類型可以配置成其內置類型之一,如 UNPOOLED,POOLED,JNDI。
? 如果將類型設置成 UNPOOLED,MyBatis 會為每一個數據庫操作創建一個新的連接,并關閉它。該方式
適用于只有小規模數量并發用戶的簡單應用程序上。
? 如果將屬性設置成 POOLED,MyBatis 會創建一個數據庫連接池,連接池中的一個連接將會被用作數據
庫操作。一旦數據庫操作完成,MyBatis 會將此連接返回給連接池。在開發或測試環境中,經常使用此
種方式。
? 如果將類型設置成 JNDI,MyBatis 從在應用服務器向配置好的 JNDI 數據源 dataSource 獲取數據庫
連接。在生產環境中,優先考慮這種方式。
?
如果屬性在不只一個地方進行了配置,那么 MyBatis 將按照下面的順序來加載:
- 在 properties 元素體內指定的屬性首先被讀取。
- 然后根據 properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據 url 屬性指定的路徑讀取屬性文件,并覆蓋已讀取的同名屬性。
- 最后讀取作為方法參數傳遞的屬性,并覆蓋已讀取的同名屬性。
因此,通過方法參數傳遞的屬性具有最高優先級,resource/url 屬性中指定的配置文件次之,最低優先級的是 properties 屬性中指定的屬性。
?
2.2?事務管理器 TransactionManager
MyBatis 支持兩種類型的事務管理器: JDBC and MANAGED.
- ?JDBC 事務管理器被用作當應用程序負責管理數據庫連接的生命周期(提交、回退等等)的時候。當你將TransactionManager 屬性設置成 JDBC,MyBatis 內部將使用 JdbcTransactionFactory 類創建TransactionManager。例如,部署到 Apache Tomcat 的應用程序,需要應用程序自己管理事務。它依賴于從數據源得到的連接來管理事務作用域。
- ?MANAGED 事務管理器是當由應用服務器負責管理數據庫連接生命周期的時候使用。當你將TransactionManager 屬性設置成 MANAGED 時,MyBatis 內部使用 ManagedTransactionFactory 類創建事務管理器TransactionManager。例如,當一個JavaEE的應用程序部署在類似 JBoss,WebLogic,GlassFish 應用服務器上時,它們會使用 EJB 進行應用服務器的事務管理能力。在這些管理環境中,你可以使用 MANAGED 事務管理器。
Managed 是托管的意思,即是應用本身不去管理事務,而是把事務管理交給應用所在的服務器進行管理。
如果你正在使用 Spring + MyBatis,則沒有必要配置事務管理器, 因為 Spring 模塊會使用自帶的管理器來覆蓋前面的配置。
?
3?類型別名 typeAliases,
配置文件中,對于 resultType 和 parameterType 屬性值,我們需要使用 JavaBean 的完全限定名。
我們可以為完全限定名取一個別名(alias),然后其需要使用完全限定名的地方使用別名,而不是到處使用完全限定名。
<typeAliases> <typeAlias alias="Student" type="com.mybatis3.domain.Student" /> <typeAlias alias="Tutor" type="com.mybatis3.domain.Tutor" /> <package name="com.mybatis3.domain" /> </typeAliases>
另一種方式為 JavaBeans 起別名,使用注解@Alias:
@Alias("StudentAlias") public class Student{}
注意:@Alias 注解將會覆蓋配置文件中的<typeAliases>定義。
?
4?類型處理器 typeHandlers
MyBatis 是怎么知道對于 Integer 類型屬性使用 setInt() 和 String 類型屬性使用 setString()方法呢?
其實 MyBatis 是通過使用類型處理器(type handlers)來決定這么做的。
MyBatis 對于以下的類型使用內建的類型處理器:所有的基本數據類型、基本類型的包裹類型、byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java 枚舉類型等。所以當 MyBatis 發現屬性的類型屬于上述類型,他會使用對應的類型處理器將值設置到 PreparedStatement 中,同樣地,當從 SQL 結果集構建 JavaBean 時,也有類似的過程。
?
對于自定義的類型,需要自己創建自定義類型處理器。
MyBatis 提供了抽象類 BaseTypeHandler<T> ,我們可以繼承此類創建自定義類型處理器。
例如,假設表 STUDENTS 有一個 PHONE 字段,類型為 VARCHAR(15),而 JavaBean Student 有一個 PhoneNumber 類定義類型的 phoneNumber 屬性。
有一個屬性是如下的類,?PhoneNumber 類


public class PhoneNumber { private String countryCode; private String stateCode; private String number; public PhoneNumber() { } public PhoneNumber(String countryCode, String stateCode, String number) { this.countryCode = countryCode; this.stateCode = stateCode; this.number = number; } public PhoneNumber(String string) { if(string != null) { String[] parts = string.split("-"); if(parts.length > 0) this.countryCode = parts[0]; if(parts.length > 1) this.stateCode = parts[1]; if(parts.length > 2) this.number = parts[2]; } } public String getAsString() { return countryCode + "-" + stateCode + "-" + number; } // Setters and getters }
?
而Student 定義如下


public class Student { private Integer id; private String name; private String email; private PhoneNumber phone; // Setters and getters }
4.1 創建的類型處理器如下
importjava.sql.CallableStatement; importjava.sql.PreparedStatement; importjava.sql.ResultSet; importjava.sql.SQLException; importorg.apache.ibatis.type.BaseTypeHandler; importorg.apache.ibatis.type.JdbcType; importcom.mybatis3.domain.PhoneNumber; public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber> { @Override public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.getAsString()); } @Override public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException { return new PhoneNumber(rs.getString(columnName)); } @Override public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return new PhoneNumber(rs.getString(columnIndex)); } @Override public PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return new PhoneNumber(cs.getString(columnIndex)); } }
說明:我們使用 ps.setString()和 rs.getString()方法是因為 phone 列是 VARCHAR 類型。
4.2?一旦我們實現了自定義的類型處理器,我們需要在 mybatis-config.xml 中注冊它:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="application.properties" /> <typeHandlers><typeHandler handler="com.mybatis3.typehandlers.PhoneTypeHandler" /> </typeHandlers> </configuration>
注冊 PhoneTypeHandler 后, MyBatis 就能夠將 Phone 類型的對象值存儲到 VARCHAR 類型的列上。
?
5?SQL 映射定義 Mappers
Mapper XML 文件中包含的 SQL 映射語句將會被應用通過使用其 statementid 來執行。我們需要在 mybatis-config.xml 文件中配置 SQL Mapper 文件的位置。
<mappers><mapper resource="com/mybatis3/mappers/StudentMapper.xml" /><mapper url="file:///D:/mybatisdemo/app/mappers/TutorMapper.xml" /><mapper class="com.mybatis3.mappers.TutorMapper" /><package name="com.mybatis3.mappers" /> </mappers>
以上每一個<mapper> 標簽的屬性有助于從不同類型的資源中加載映射 mapper:
? resource 屬性用來指定在 classpath 中的 mapper 文件。
? url 屬性用來通過完全文件系統路徑或者 web URL 地址來指向 mapper 文件
? class 屬性用來指向一個 mapper 接口
? package 屬性用來指向可以找到 Mapper 接口的包名
?