## 概述 Mybatis 的核心組件如下所示: - Configuration:用於描述 MyBatis 的主配置信息,其他組件需要獲取配置信息時,直接通過 Configuration 對象獲取。除此之外,MyBatis 在應用啟動時,將 Mapper 配置信息、類型別名、TypeHandler ...
概述
Mybatis 的核心組件如下所示:
- Configuration:用於描述 MyBatis 的主配置信息,其他組件需要獲取配置信息時,直接通過 Configuration 對象獲取。除此之外,MyBatis 在應用啟動時,將 Mapper 配置信息、類型別名、TypeHandler 等註冊到 Configuration 組件中,其他組件需要這些信息時,也可以從 Configuration 對象中獲取
- MappedStatement:用於描述 Mapper 中的 SQL 配置信息,是對 Mapper XML 配置文件中
<select|update|delete|insert>
等標簽或者@Select/@Update
等註解配置信息的封裝 - SqlSession:是 MyBatis 提供的面向用戶的 API,表示和資料庫交互時的會話對象,用於完成資料庫的增刪改查功能。SqlSession 是 Executor 組件的外觀,目的是對外提供易於理解和使用的資料庫操作介面
- Executor:MyBatis 的 SQL 執行器,MyBatis 對資料庫所有的增刪改查操作都是由 Executor 組件完成的
- StatementHandler:封裝了對 JDBC Statement 對象的操作,比如為 Statement 對象設置參數,調用 Statement 介面提供的方法與資料庫交互等等
- ParameterHandler:當 MyBatis 框架使用的 Statement 類型為 CallableStatcment 和 PreparedStatement 時,ParamelerHandler 用於為 Statement 對象參數占位符設置值
- ResultSetHandler:ResultSetHandler 封裝了對 JDBC 的 ResultSet 對象操作,當執行 SQL 類型為 SELECT 語句時,ResultSetHandler 用於將查詢結果轉換成 Java 對象
- TypeHandler:TypeHandler 是 MyBatis 中的類型處理器,用於處理 Java 類型與 JDBC 類型之間的映射,它的作用主要體現在能夠根據 Java 類型調用 PreparedStatement 或 CallableStatement 對象對應的 set 方法為 Statement 對象設置值,而且能夠根據 Java 類型調用 ResultSet 對象對應的 get 獲取SQL執行結果
在使用 MyBatis 時,我們使用到 SqlSession 組件,它是用戶層面的 API。實際上 SqlSession 是Executor 組件的外觀,目的是為用戶提供更友好的資料庫操作介面,這是設計模式中外觀模式的典型應用。真正執行 SQL 操作的是 Executor 組件,Executor 可以理解為 SQL 執行器,它會使用 StatementHandler 組件對 JDBC 的 Statement 對象進行操作。當 Statement 類型為 CallableStatement 和 PreparedStatement 時,會通過 ParameterHandler 組件為參數占位符賦值。ParameterHandler 組件中會根據 Java 類型找到對應的 TypeHandler 對象,TypeHandler 會通過 Statement 對象提供的set 方法為 Statement 對象中的參數占位符設置值。StatementHandler 組件使用 JDBC 中的 Statement 對象與資料庫完成交互後,當 SQL 語句類型為 SELECT 時,MyBatis 通過 ResultSetHandler 組件從 Statement 對象中獲取 ResultSet 對象,然後將 ResultSet 對象轉換為 Java 對象
Configuration
MyBatis 框架的配置信息有兩種,一種是配置 MyBatis 框架屬性的主配置文件;另一種是配置執行 SQL 語句的 Mapper 配置文件。Configuration 的作用是描述 MyBatis 主配置文件的信息。Configuration 類中定義了一系列的屬性用來控制MyBatis 運行時的行為,這些屬性代碼如下:
public class Configuration {
protected boolean safeRowBoundsEnabled;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase;
protected boolean aggressivelazyLoading;
protected boolean multipleResultSetsEnabled = true;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel = true;
.......
}
這些屬性的值可以在MyBatis主配置文件中通過 <setting>
標簽指定,例如:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
所有屬性的作用及配置說明參考如下:
- cacheEnabled:是否開啟 Mapper 緩存,即二級緩存,預設 true
- lazyLoadingEnabled:延遲載入的全局開關。當開啟時,所有關聯對象都會延遲載入。特定關聯關係中可通過設置 fetchType 屬性來覆蓋該項的開關狀態,預設 false
- aggressiveLazyLoading:當開啟時,任何方法的調用都會載入該對象的所有屬性。否則,每個屬性會按需載入,預設 false,3.4.1 之前預設為 true
- multipleResultSetsEnabled:是否允許單一語句返回多結果集,預設 true
- useColumnLabel:使用列標簽代替列名,不同的驅動在這方面會有不同的表現,預設 true
- useGeneratedKeys:允許 JDBC 支持自動生成主鍵,需要驅動相容。如果設置為 true,則這個設置強制使用自動生成主鍵,儘管一些驅動不能相容,但仍可正常工作,預設 false
- autoMappingBehavior:指定 MyBatis 應該如何自動映射列到 Java 實體屬性。NONE 表示取消自動映射,PARTIAL 只會自動映射沒有定義嵌套結果集映射的結果集。FULL 會自動映射任意複雜的結果集(無論是否嵌套),預設 PARTIAL
- autoMappingUnknownColumnBehavior:指定發現自動映射目標未知列(或者未知屬性)的行為。NONE:不做任何反應,WARNING:輸出提醒日誌,FAILING:映射失敗,拋出異常,預設 NONE
- defaultExecutorType:配置預設的 Executor 類型,SIMPLE 就是普通的 Executor;REUSE 會復用 Statement 對象;BATCH 會批量執行所有更新語句,預設 SIMPLE
- defaultStatementTimeout:設置超時時間,它決定驅動等待資料庫響應的秒數,可以說任意正整數,預設為 null 未設置
- defaultFetchSize:預設的 FetchSize,用於設置 Statement 對象的 fetchSize 屬性,用於限制從資料庫中獲取數據的最大行數,預設為 null 未設置
- SafeRowBoundsEnabled:允許在嵌套語句中使用分頁(RowBounds),如果允許使用,則設置為 false,預設 false
- safeResultHandlerEnabled:允許在嵌套語句中使用分頁(ResultHandler),如果允許使用,則設置為 false,預設 false
- mapUnderscoreToCamelCase:是否開啟自動駝峰命名規則映射,即從經典資料庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的映射
- localCacheScope:MyBatis 利用本地緩存機制防止迴圈引用和加速重覆查詢。預設值為 SESSION,這種情況下會緩存個會話中執行的所有查詢。若設置值為 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不同調用將不會共用數據
- jdbcTypeForNuIl:當沒有為參數指定 JDBC 類型時,指定 JDBC 類型的值為null。一些驅動需要指定 JDBC 類型,多數情況下直接用一般類型即可,比如 NULL、VARCHAR 或 OTHER,預設 OTHER
- lazyLoadTriggerMethods:指定哪個對象的方法會觸發一次延遲載入,參數是用逗號分割的方法列表
- defaultScriptingLanguage:指定動態 SQL 生成的預設語言,參數值為一個類型別名或完全限定類名,預設值:org.apache.ibatis.XMLLanguageDriver
- defaultEnumTypeHandler:指定 Java 枚舉類型使用的預設 TypeHandler,預設值:org.apache.ibatis.type.EnumTypeHandler
- callSettersOnNulls:指定當結果集中的值為 null 的時候是否調用映射對象的Setter方法,這對於有 Map.keySet() 依賴或 null 值初始化的時候是有用的。註意基本類型(int、boolean 等)是不能設置成 null 的,預設 false
- returnInstanceForEmptyRow:當返回行的所有列都是空時,MyBatis 預設返回null。當開啟這個設置時,MyBatis 會返回一個空實例。請註意,也適用於嵌套的結果集(collection、association),預設 false
- logPrefix:指定 MyBatis 增加到日誌名稱的首碼,預設未設置
- loglmpl:指定MyBatis 所用日誌的具體實現,未指定時將自動查找,可設置 SLF4J、LOG4J等,預設未設置
- proxyFactory:指定MyBatis 創建具有延遲載入能力的對象所用到的代理工具,可選值有 JAVASSIST、CGLIB,預設 JAVASSIST
- vfsImpl:指定 VFS 的實現,參數我 VFS 的實現類的全限定名,以逗號分隔,預設未設置
Configuration 除了提供上面的屬性控制 MyBatis 的行為外,還作為容器存放 TypeHandler(類型處理器)、TypeAlias(類型別名)、Mapper 介面及 MapperSQL 配置信息。這些信息在 MyBatis 框架啟動時註冊到 Configuration 組件中。Configuration 類通過下麵的屬性保存 TypeHandler、TypeAlias 等信息:
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
protected final InterceptorChain interceptorChain = new InterceptorChain();
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
protected final TypeAliasRegistry typeAliasRegistry= new TypeAliasRegistry();
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");
protected final Set<String> loadedResources = new HashSet<String>();
protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
protected final Collection<CacheRefResolver> incompletecacheRefs = new LinkedList<CacheRefResolver>()
protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();
protected final Map<String, String> cacheRefMap = new HashMap<String, String>();
這些屬性的含義如下:
- mapperRegistry:用於註冊 Mapper 介面信息,建立 Mapper 介面的 Class 對象和 MapperProxyFactory 對象之間的關係,其中 MapperProxyFactory 對象用於創建 Mapper 動態代理對象
- interceptorChain:用於註冊 MyBatis 插件信息,MyBatis 插件實際上就是一個攔截器
- typeHandlerRegistry:用於註冊所有的 TypeHandler,並建立 Jdbc 類型、JDBC 類型與 TypeHandler 之間的對應關係
- typeAliasRegistry:用於註冊所有的類型別名
- languageRegistry:用於註冊 LanguageDriver,LanguageDriver 用於解析 SQL 配置,將配置信息轉換為 SqlSource 對象
- mappedStatements:MappedStatement 對象描述
<insert|selectlupdateldelete>
等標簽或者通過@Select|@Delete|@Update|@Insert
等註解配置的 SQL 信息。MyBatis 將所有的 MappedStatement 對象註冊到該屬性中,其中 Key 為 Mapper 的 Id, Value 為 MappedStatement 對象 - caches:用於註冊 Mapper 中配置的所有緩存信息,其中 Key 為 Cache 的 id,也就是 Mapper 的命名空間,Value 為 Cache 對象
- resultMaps:用於註冊 Mapper 配置文件中通過
標簽配置的 ResultMap 信息,ResultMap 用於建立 Java 實體屬性與資料庫欄位之間的映射關係,其中 Key 為 ResultMap 的 id,該 id 是由 Mapper 命名空間和 標簽的 id 屬性組成的,Value 為解析 標簽後得到的 ResultMap 對象 - parameterMaps:用於註冊 Mapper 中通過
標簽註冊的參數映射信息。Key 為 ParameterMap 的 id,由 Mapper 命名空間和 標簽的 id 屬性構成,Value 為解析 標簽後得到的 ParameterMap 對象 - keyGenerators:用於註冊 KeyGenerator,KeyGenerator 是 MyBatis 的主鍵生成器,MyBatis 提供了三種KeyGenerator,即 Jdbc3KeyGenerator(資料庫自增主鍵)、NoKeyGenerator(無自增主鍵)、SelectKeyGenerator(通過 select 語句查詢自增主鍵,例如 oracle 的 sequence)
- loadedResources:用於註冊所有 Mapper XML 配置文件路徑
- sqlFragments:用於註冊 Mapper 中通過
標簽配置的 SQL 片段,Key 為 SQL 片段的 id,Value 為 MyBatis 封裝的表示 XML 節點的 XNode 對象 - incompleteStatements:用於註冊解析出現異常的 XMLStatementBuilder 對象
- incompleteCacheRefs:用於註冊解析出現異常的 CacheRefResolver 對象
- incompleteResultMaps:用於註冊解析出現異常的 ResultMapResolver 對象
- incompleteMethods:用於註冊解析出現異常的 MethodResolver 對象
MyBatis 框架啟動時,會對所有的配置信息進行解析,然後將解析後的內容註冊到 Configuration 對象的這些屬性中。除此之外,Configuration 組件還作為 Executor、StatementHandler、ResultSetHandler、ParameterHandler 組件的工廠類,用於創建這些組件的實例。