大部分時候,咱們都是在Spring 裏面去集成MyBatis。由於Spring 對MyBatis 的一些操做進行的封裝,咱們不能直接看到它的本質,因此先看下不使用容器的時候,也就是編程的方式,MyBatis 怎麼使用。先引入mybatis jar 包。html
首先咱們要建立一個全局配置文件,這裏面是對MyBatis 的核心行爲的控制,好比mybatis-config.xml。java
第二個就是咱們的映射器文件,Mapper.xml,一般來講一張表對應一個,咱們會在這個裏面配置咱們增刪改查的SQL 語句,以及參數和返回的結果集的映射關係。跟JDBC 的代碼同樣,咱們要執行對數據庫的操做,必須建立一個會話,這個在MyBatis 裏面就是SqlSession。SqlSession 又是工廠類根據全局配置文件建立的。因此整個的流程就是這樣的(以下代碼)。最後咱們經過SqlSession 接口上的方法,傳入咱們的Statement ID 來執行SQL。這是第一種方式。sql
這種方式有一個明顯的缺點,就是會對Statement ID 硬編碼,並且不能在編譯時進行類型檢查,因此一般咱們會使用第二種方式,就是定義一個Mapper 接口的方式。這個接口全路徑必須跟Mapper.xml 裏面的namespace 對應起來,方法也要跟StatementID 一一對應。數據庫
public void testMapper() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = mapper.selectBlogById(1); System.out.println(blog); } finally { session.close(); } }
這個就是咱們單獨使用MyBatis 的基本流程。apache
在編程式使用的這個demo 裏面,咱們看到了MyBatis 裏面的幾個核心對象:SqlSessionFactoryBuiler、SqlSessionFactory、SqlSession 和Mapper 對象。這幾個核心對象在MyBatis 的整個工做流程裏面的不一樣環節發揮做用。若是說咱們不用容器,本身去管理這些對象的話,咱們必須思考一個問題:何時建立和銷燬這些對象?在一些分佈式的應用裏面,多線程高併發的場景中,若是要寫出高效的代碼,必須瞭解這四個對象的生命週期。這四個對象的聲明週期的描述在官網上面也能夠找到。咱們從每一個對象的做用的角度來理解一下,只有理解了它們是幹什麼的,才知道何時應該建立,何時應該銷燬。編程
這個類能夠被實例化、使用和丟棄,一旦建立了 SqlSessionFactory,就再也不須要它了。 所以 SqlSessionFactoryBuilder 實例的最佳做用域是方法做用域(也就是局部方法變量)。 你能夠重用 SqlSessionFactoryBuilder 來建立多個 SqlSessionFactory 實例,可是最好仍是不要讓其一直存在,以保證全部的 XML 解析資源能夠被釋放給更重要的事情。緩存
SqlSessionFactory 一旦被建立就應該在應用的運行期間一直存在,沒有任何理由丟棄它或從新建立另外一個實例。 使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重複建立屢次,屢次重建 SqlSessionFactory 被視爲一種代碼「壞味道(bad smell)」。所以 SqlSessionFactory 的最佳做用域是應用做用域。 有不少方法能夠作到,最簡單的就是使用單例模式或者靜態單例模式。安全
每一個線程都應該有它本身的 SqlSession 實例。SqlSession 的實例不是線程安全的,所以是不能被共享的,因此它的最佳的做用域是請求或方法做用域。 絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。 也毫不能將 SqlSession 實例的引用放在任何類型的託管做用域中,好比 Servlet 框架中的 HttpSession。 若是你如今正在使用一種 Web 框架,要考慮 SqlSession 放在一個和 HTTP 請求對象類似的做用域中。 換句話說,每次收到的 HTTP 請求,就能夠打開一個 SqlSession,返回一個響應,就關閉它。 這個關閉操做是很重要的,你應該把這個關閉操做放到 finally 塊中以確保每次都能執行關閉。 下面的示例就是一個確保 SqlSession 關閉的標準模式:服務器
SqlSession session = sqlSessionFactory.openSession(); try { // 你的應用邏輯代碼 } finally { session.close(); }
在你的全部的代碼中一致地使用這種模式來保證全部數據庫資源都能被正確地關閉。網絡
映射器是一些由你建立的、綁定你映射的語句的接口。映射器接口的實例是從 SqlSession 中得到的。所以從技術層面講,任何映射器實例的最大做用域是和請求它們的 SqlSession 相同的。儘管如此,映射器實例的最佳做用域是方法做用域。 也就是說,映射器實例應該在調用它們的方法中被請求,用過以後便可丟棄。 並不須要顯式地關閉映射器實例,儘管在整個請求做用域保持映射器實例也不會有什麼問題,可是你很快會發現,像 SqlSession 同樣,在這個做用域上管理太多的資源的話會難於控制。 爲了不這種複雜性,最好把映射器放在方法做用域內。下面的示例就展現了這個實踐:
SqlSession session = sqlSessionFactory.openSession(); try { BlogMapper mapper = session.getMapper(BlogMapper.class); // 你的應用邏輯代碼 } finally { session.close(); }
這個就是咱們在編程式的使用裏面看到的四個對象的生命週期的總結。
第一個是config 文件。大部分時候咱們只須要不多的配置就可讓MyBatis 運行起來。其實MyBatis 裏面提供的配置項很是多,咱們沒有配置的時候使用的是系統的默認值。
目前最新的版本是3.5.1,你們能夠從官方上下載到最新的源碼。中文地址:http://www.mybatis.org/mybatis-3/zh/index.html
<?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="db.properties"></properties> <settings> <!-- 打印查詢語句 --> <setting name="logImpl" value="STDOUT_LOGGING" /> <!-- 控制全局緩存(二級緩存)--> <setting name="cacheEnabled" value="true"/> <!-- 延遲加載的全局開關。當開啓時,全部關聯對象都會延遲加載。默認 false --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 當開啓時,任何方法的調用都會加載該對象的全部屬性。默認 false,可經過select標籤的 fetchType來覆蓋--> <setting name="aggressiveLazyLoading" value="false"/> <!-- Mybatis 建立具備延遲加載能力的對象所用到的代理工具,默認JAVASSIST --> <!--<setting name="proxyFactory" value="CGLIB" />--> <!-- STATEMENT級別的緩存,使一級緩存,只針對當前執行的這一statement有效 --> <!-- <setting name="localCacheScope" value="STATEMENT"/> --> <setting name="localCacheScope" value="SESSION"/> </settings> <typeAliases> <typeAlias alias="blog" type="com.wuzz.domain.Blog" /> </typeAliases> <!-- <typeHandlers> <typeHandler handler="com.wuzz.type.MyTypeHandler"></typeHandler> </typeHandlers>--> <!-- 對象工廠 --> <!-- <objectFactory type="com.wuzz.objectfactory.GPObjectFactory"> <property name="wuzz" value="666"/> </objectFactory>--> <!-- <plugins> <plugin interceptor="com.wuzz.interceptor.SQLInterceptor"> <property name="wuzz" value="betterme" /> </plugin> <plugin interceptor="com.wuzz.interceptor.MyPageInterceptor"> </plugin> </plugins>--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/><!-- 單獨使用時配置成MANAGED沒有事務 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="BlogMapper.xml"/> <mapper resource="BlogMapperExt.xml"/> </mappers> </configuration>
configuration 是整個配置文件的根標籤,實際上也對應着MyBatis 裏面最重要的配置類Configuration。它貫穿MyBatis 執行流程的每個環節。這裏面有不少的屬性,跟其餘的子標籤也能對應上。
注意:MyBatis 全局配置文件順序是固定的,不然啓動的時候會報錯。
第一個是properties 標籤,用來配置參數信息,好比最多見的數據庫鏈接信息。爲了不直接把參數寫死在xml 配置文件中,咱們能夠把這些參數單獨放在properties 文件中,用properties 標籤引入進來,而後在xml 配置文件中用${}引用就能夠了。能夠用resource 引用應用裏面的相對路徑,也能夠用url 指定本地服務器或者網絡的絕對路徑。
咱們爲何要把這些配置獨立出來?有什麼好處?或者說,公司的項目在打包的時候,有沒有把properties 文件打包進去?
這是 MyBatis 中極爲重要的調整設置,它們會改變 MyBatis 的運行時行爲。 下表描述了設置中各項的意圖、默認值等。
設置名 | 描述 | 有效值 | 默認值 |
---|---|---|---|
cacheEnabled | 全局地開啓或關閉配置文件中的全部映射器已經配置的任何緩存。 | true | false | true |
lazyLoadingEnabled | 延遲加載的全局開關。當開啓時,全部關聯對象都會延遲加載。 特定關聯關係中可經過設置 fetchType屬性來覆蓋該項的開關狀態。 | true | false | false |
aggressiveLazyLoading | 當開啓時,任何方法的調用都會加載該對象的全部屬性。 不然,每一個屬性會按需加載(參考 lazyLoadTriggerMethods)。 | true | false | false (在 3.4.1 及以前的版本默認值爲 true) |
multipleResultSetsEnabled | 是否容許單一語句返回多結果集(須要驅動支持)。 | true | false | true |
useColumnLabel | 使用列標籤代替列名。不一樣的驅動在這方面會有不一樣的表現,具體可參考相關驅動文檔或經過測試這兩種不一樣的模式來觀察所用驅動的結果。 | true | false | true |
useGeneratedKeys | 容許 JDBC 支持自動生成主鍵,須要驅動支持。 若是設置爲 true 則這個設置強制使用自動生成主鍵,儘管一些驅動不能支持但仍可正常工做(好比 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 應如何自動映射列到字段或屬性。 NONE 表示取消自動映射;PARTIAL 只會自動映射沒有定義嵌套結果集映射的結果集。 FULL 會自動映射任意複雜的結果集(不管是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定發現自動映射目標未知列(或者未知屬性類型)的行爲。
|
NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默認的執行器。SIMPLE 就是普通的執行器;REUSE 執行器會重用預處理語句(prepared statements); BATCH 執行器將重用語句並執行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 設置超時時間,它決定驅動等待數據庫響應的秒數。 | 任意正整數 | 未設置 (null) |
defaultFetchSize | 爲驅動的結果集獲取數量(fetchSize)設置一個提示值。此參數只能夠在查詢設置中被覆蓋。 | 任意正整數 | 未設置 (null) |
safeRowBoundsEnabled | 容許在嵌套語句中使用分頁(RowBounds)。若是容許使用則設置爲 false。 | true | false | False |
safeResultHandlerEnabled | 容許在嵌套語句中使用分頁(ResultHandler)。若是容許使用則設置爲 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否開啓自動駝峯命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的相似映射。 | true | false | False |
localCacheScope | MyBatis 利用本地緩存機制(Local Cache)防止循環引用(circular references)和加速重複嵌套查詢。 默認值爲 SESSION,這種狀況下會緩存一個會話中執行的全部查詢。 若設置值爲 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不一樣調用將不會共享數據。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 當沒有爲參數提供特定的 JDBC 類型時,爲空值指定 JDBC 類型。 某些驅動須要指定列的 JDBC 類型,多數狀況直接用通常類型便可,好比 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,經常使用值:NULL, VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定哪一個對象的方法觸發一次延遲加載。 | 用逗號分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定動態 SQL 生成的默認語言。 | 一個類型別名或徹底限定類名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定 Enum 使用的默認 TypeHandler 。(新增於 3.4.5) | 一個類型別名或徹底限定類名。 | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | 指定當結果集中值爲 null 的時候是否調用映射對象的 setter(map 對象時爲 put)方法,這在依賴於 Map.keySet() 或 null 值初始化的時候比較有用。注意基本類型(int、boolean 等)是不能設置成 null 的。 | true | false | false |
returnInstanceForEmptyRow | 當返回行的全部列都是空時,MyBatis默認返回 null。 當開啓這個設置時,MyBatis會返回一個空實例。 請注意,它也適用於嵌套的結果集 (如集合或關聯)。(新增於 3.4.2) | true | false | false |
logPrefix | 指定 MyBatis 增長到日誌名稱的前綴。 | 任何字符串 | 未設置 |
logImpl | 指定 MyBatis 所用日誌的具體實現,未指定時將自動查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未設置 |
proxyFactory | 指定 Mybatis 建立具備延遲加載能力的對象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
vfsImpl | 指定 VFS 的實現 | 自定義 VFS 的實現的類全限定名,以逗號分隔。 | 未設置 |
useActualParamName | 容許使用方法簽名中的名稱做爲語句參數名稱。 爲了使用該特性,你的項目必須採用 Java 8 編譯,而且加上 -parameters 選項。(新增於 3.4.1) | true | false | true |
configurationFactory | 指定一個提供 Configuration 實例的類。 這個被返回的 Configuration 實例用來加載被反序列化對象的延遲加載屬性值。 這個類必須包含一個簽名爲static Configuration getConfiguration() 的方法。(新增於 3.2.3) | 類型別名或者全類名. | 未設置 |
TypeAlias 是類型的別名,跟Linux 系統裏面的alias 同樣,主要用來簡化全路徑類名的拼寫。好比咱們的參數類型和返回值類型均可能會用到咱們的Bean,若是每一個地方都配置全路徑的話,那麼內容就比較多,還可能會寫錯。咱們能夠爲本身的Bean 建立別名,既能夠指定單個類,也能夠指定一個package,自動轉換。配置了別名之後,只須要寫別名就能夠了,好比com.gupaoedu.domain.Blog都只要寫blog 就能夠了。MyBatis 裏面有系統預先定義好的類型別名,在TypeAliasRegistry 中。
<typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> </typeAliases>
當這樣配置時,Blog 能夠用在任何使用 domain.blog.Blog 的地方。也能夠指定一個包名,MyBatis 會在包名下面搜索須要的 Java Bean,好比:
<typeAliases> <package name="domain.blog"/> </typeAliases>
每個在包 domain.blog 中的 Java Bean,在沒有註解的狀況下,會使用 Bean 的首字母小寫的非限定類名來做爲它的別名。 好比 domain.blog.Author 的別名爲 author;如有註解,則別名爲其註解值。見下面的例子:
@Alias("author") public class Author { ... }
因爲Java 類型和數據庫的JDBC 類型不是一一對應的(好比String 與varchar),因此咱們把Java 對象轉換爲數據庫的值,和把數據庫的值轉換成Java 對象,須要通過必定的轉換,這兩個方向的轉換就要用到TypeHandler。有的同窗可能會有疑問,我沒有作任何的配置,爲何實體類對象裏面的一個String屬性,能夠保存成數據庫裏面的varchar 字段,或者保存成char 字段?這是由於MyBatis 已經內置了不少TypeHandler(在type 包下),它們所有所有註冊在TypeHandlerRegistry 中,他們都繼承了抽象類BaseTypeHandler,泛型就是要處理的Java 數據類型。
當咱們作數據類型轉換的時候,就會自動調用對應的TypeHandler 的方法。若是咱們須要自定義一些類型轉換規則,或者要在處理類型的時候作一些特殊的動做,就能夠編寫本身的TypeHandler,跟系統自定義的TypeHandler 同樣,繼承抽象類BaseTypeHandler<T>。有4 個抽象方法必須實現,咱們把它分紅兩類:set 方法從Java 類型轉換成JDBC 類型的,get 方法是從JDBC 類型轉換成Java 類型的。
好比咱們想要在獲取或者設置String 類型的時候作一些特殊處理,咱們能夠寫一個String 類型的TypeHandler
public class MyTypeHandler extends BaseTypeHandler<String> { public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { // 設置 String 類型的參數的時候調用,Java類型到JDBC類型 // 注意只有在字段上添加typeHandler屬性纔會生效 // insertBlog name字段 System.out.println("---------------setNonNullParameter1:"+parameter); ps.setString(i, parameter); } public String getNullableResult(ResultSet rs, String columnName) throws SQLException { // 根據列名獲取 String 類型的參數的時候調用,JDBC類型到java類型 // 注意只有在字段上添加typeHandler屬性纔會生效 System.out.println("---------------getNullableResult1:"+columnName); return rs.getString(columnName); } public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { // 根據下標獲取 String 類型的參數的時候調用 System.out.println("---------------getNullableResult2:"+columnIndex); return rs.getString(columnIndex); } public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { System.out.println("---------------getNullableResult3:"); return cs.getString(columnIndex); } }
第二步,在mybatis-config.xml 文件中註冊:
<typeHandlers> <typeHandler handler="com.wuzz.type.MyTypeHandler"></typeHandler> </typeHandlers>
第三步,在咱們須要使用的字段上指定,好比:插入值的時候,從Java 類型到JDBC 類型,在字段屬性中指定typehandler:
<insert id="insertBlog" parameterType="com.wuzz.domain.Blog"> insert into blog (bid, name, author_id) values (#{bid,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR,typeHandler=com.wuzz.type.MyTypeHandler}, #{authorId,jdbcType=INTEGER}) </insert>
返回值的時候,從JDBC 類型到Java 類型,在resultMap 的列上指定typehandler:
<result column="name" property="name" jdbcType="VARCHAR" typeHandler="com.wuzz.type.MyTypeHandler"/>
處理枚舉類型
若想映射枚舉類型 Enum,則須要從 EnumTypeHandler 或者 EnumOrdinalTypeHandler 中選一個來使用。
好比說咱們想存儲取近似值時用到的舍入模式。默認狀況下,MyBatis 會利用 EnumTypeHandler 來把 Enum 值轉換成對應的名字。
注意 EnumTypeHandler 在某種意義上來講是比較特別的,其餘的處理器只針對某個特定的類,而它不一樣,它會處理任意繼承了 Enum 的類。
不過,咱們可能不想存儲名字,相反咱們的 DBA 會堅持使用整形值代碼。那也同樣垂手可得: 在配置文件中把 EnumOrdinalTypeHandler 加到 typeHandlers 中便可, 這樣每一個 RoundingMode 將經過他們的序數值來映射成對應的整形數值。
當咱們把數據庫返回的結果集轉換爲實體類的時候,須要建立對象的實例,因爲咱們不知道須要處理的類型是什麼,有哪些屬性,因此不能用new 的方式去建立。在MyBatis 裏面,它提供了一個工廠類的接口,叫作ObjectFactory,專門用來建立對象的實例,裏面定義了4 個方法。
public interface ObjectFactory { void setProperties(Properties var1); <T> T create(Class<T> var1); <T> T create(Class<T> var1, List<Class<?>> var2, List<Object> var3); <T> boolean isCollection(Class<T> var1); }
ObjectFactory 有一個默認的實現類DefaultObjectFactory,建立對象的方法最終都調用了instantiateClass(),是經過反射來實現的。若是想要修改對象工廠在初始化實體類的時候的行爲,就能夠經過建立本身的對象工廠,繼承DefaultObjectFactory 來實現(不須要再實現ObjectFactory 接口)。
public class MyObjectFactory extends DefaultObjectFactory { @Override public Object create(Class type) { System.out.println("建立對象方法:" + type); if (type.equals(Blog.class)) { Blog blog = (Blog) super.create(type); blog.setName("object factory"); blog.setBid(1111); blog.setAuthorId(2222); return blog; } Object result = super.create(type); return result; } }
咱們能夠直接用自定義的工廠類來建立對象:
public class ObjectFactoryTest { public static void main(String[] args) { MyObjectFactory factory = new MyObjectFactory(); Blog myBlog = (Blog) factory.create(Blog.class); System.out.println(myBlog); } }
應用場景舉例:
好比有一個新銳手機品牌在一個電商平臺上面賣貨,爲了讓預定數量好看一點,只要有人預定,預定數量就自動乘以3。這個時候就能夠建立一個ObjectFactory,只要是查詢銷量,就把它的預定數乘以3 返回這個實體類。
一、何時調用了objectFactory.create()?
建立DefaultResultSetHandler 的時候,和建立對象的時候。
二、建立對象後,已有的屬性爲何被覆蓋了?
在DefaultResultSetHandler 類的395 行getRowValue()方法裏面裏面調用了applyPropertyMappings()。
三、返回結果的時候,ObjectFactory 和TypeHandler 哪一個先工做?
先是ObjectFactory,再是TypeHandler。確定是先建立對象。PS:step out 能夠看到一步步調用的層級。
MyBatis 容許你在已映射語句執行過程當中的某一點進行攔截調用。默認狀況下,MyBatis 容許使用插件來攔截的方法調用包括:
這些類中方法的細節能夠經過查看每一個方法的簽名來發現,或者直接查看 MyBatis 發行包中的源代碼。 若是你想作的不只僅是監控方法的調用,那麼你最好至關了解要重寫的方法的行爲。 由於若是在試圖修改或重寫已有方法的行爲的時候,你極可能在破壞 MyBatis 的核心模塊。 這些都是更低層的類和方法,因此使用插件的時候要特別小心。經過 MyBatis 提供的強大機制,使用插件是很是簡單的,只需實現 Interceptor 接口,並指定想要攔截的方法簽名便可。
// ExamplePlugin.java @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { } }
<!-- mybatis-config.xml --> <plugins> <plugin interceptor="org.mybatis.example.ExamplePlugin"> <property name="someProperty" value="100"/> </plugin> </plugins>
上面的插件將會攔截在 Executor 實例中全部的 「update」 方法調用, 這裏的 Executor 是負責執行低層映射語句的內部對象。
environments 標籤用來管理數據庫的環境,好比咱們能夠有開發環境、測試環境、生產環境的數據庫。能夠在不一樣的環境中使用不一樣的數據庫地址或者類型。
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/><!-- 單獨使用時配置成MANAGED沒有事務 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments>
一個environment 標籤就是一個數據源,表明一個數據庫。這裏面有兩個關鍵的標籤,一個是事務管理器,一個是數據源。
transactionManager
若是配置的是JDBC,則會使用Connection 對象的commit()、rollback()、close()管理事務。若是配置成MANAGED,會把事務交給容器來管理,好比JBOSS,Weblogic。由於咱們跑的是本地程序,若是配置成MANAGE 不會有任何事務。若是是Spring + MyBatis , 則沒有必要配置, 由於咱們會直接在applicationContext.xml 裏面配置數據源,覆蓋MyBatis 的配置。
<mappers>標籤配置的是咱們的映射器,也就是Mapper.xml 的路徑。這裏配置的目的是讓MyBatis 在啓動的時候去掃描這些映射器,建立映射關係。咱們有四種指定Mapper 文件的方式:
<!-- 使用相對於類路徑的資源引用 --> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers> <!-- 使用徹底限定資源定位符(URL) --> <mappers> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper url="file:///var/mappers/BlogMapper.xml"/> <mapper url="file:///var/mappers/PostMapper.xml"/> </mappers> <!-- 使用映射器接口實現類的徹底限定類名 --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers> <!-- 將包內的映射器接口實現所有註冊爲映射器 --> <mappers> <package name="org.mybatis.builder"/> </mappers>