深入理解MyBatis的原理(三):配置文件(上)
前言:前文提到一個入門的demo,從這里開始,會了解深入 MyBatis 的配置,本文講解 MyBatis 的配置文件的用法。
目錄
1、properties 元素
2、設(shè)置(settings)
3、別名(typeAliases)
配置 XML 文件的層次結(jié)構(gòu)?
<?xml version="1.0" encoding="UTF-8"?> <configuration><!--配置--><properties/><!--屬性--><settions/><!--設(shè)置--><typeAliases/><!--類型命名,不區(qū)分大小寫--><typeHandlers/><!--類型處理器--><objectFactory/><!--對象工廠--><plugins/><!--插件--><environments><!--配置環(huán)境--><environment><transactionManager/><!--事務(wù)管理器--><dataSource/><!--數(shù)據(jù)源--></environment></environments><databaseIdProvider/><!--數(shù)據(jù)庫廠商標(biāo)識--><mappers/><!--映射器--> </configuration>注意:MyBatis 配置 XML 文件的層次結(jié)構(gòu)。這些層次是不能夠顛倒順序的,如果顛倒順序,MyBatis 在解析 XML 文件的時候就會出現(xiàn)異常。
xml 為什么不能顛倒順序
至于為什么不能顛倒順序,是由于 MyBatis3 是使用 dtd 文件作為 xml 文件的格式校驗(yàn)的,而在 xml 規(guī)范中,dtd 是有嚴(yán)格校驗(yàn)順序的。
在 idea 中,如果顛倒順序,idea 會提示下圖信息:
查看源碼可以得知,在 org/apache/ibatis/builder/xml/mybatis-3-config.dtd 文件中,有明確定義該順序:
1、properties 元素
properties 是一個配置屬性的元素,讓我們能夠在配置文件的上下文中(其他配置屬性里面,比如環(huán)境配置)使用它。
我們可以有 3 種配置方式:property 子元素、properties 配置文件、程序的參數(shù)傳遞。
1.1、property 子元素
dtd 的規(guī)則
配置好后在數(shù)據(jù)庫環(huán)境配置里使用
<!--屬性,property 子元素--><properties><property name="driver" value="oracle.jdbc.OracleDriver"/><property name="datasourceurl" value="jdbc:oracle:thin:@localhost:1521:ORCL"/><property name="username" value="testdev"/><property name="password" value="test1234"/></properties><!--配置環(huán)境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${datasourceurl}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>1.2 properties 配置文件
經(jīng)常,我們都喜歡使用 properties 配置文件來配置屬性值,方便我們在多個配置文件中重復(fù)使用,更是為了方便系統(tǒng)上線后的維護(hù)和修改。
dtd 的規(guī)則
建一個 db.properties 文件
driver=oracle.jdbc.OracleDriver datasourceurl=jdbc:oracle:thin:@localhost:1521:ORCL username=testdev password=test1234配置文件
<properties resource="config/system/db.properties"/><!--配置環(huán)境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${datasourceurl}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>1.3 程序參數(shù)傳遞
有時,我們的數(shù)據(jù)庫名和密碼不對開發(fā)公布,而是由運(yùn)維人員配置的,所以這是數(shù)據(jù)庫名和密碼可以加密配置在 db.properties 文件中,然后由程序去 decode,創(chuàng)建 sqlSessionFactory 時采用 SqlSessionFactoryBuilder 的?public SqlSessionFactory build(Reader reader, Properties roperties) 方法。
程序部分代碼如下
/*** 初始化sqlSessionFactory,針對數(shù)據(jù)庫的密碼和用戶名加密的情況* @throws IOException*/public void initSqlSessionFactoryForEncodeDbInfo() throws IOException {//讀入配置文件流InputStream inputStream = Resources.getResourceAsStream("configuration.xml");Reader reader = new InputStreamReader(inputStream);//讀入屬性文件Reader propertiesReader = new InputStreamReader(Resources.getResourceAsStream("config/system/db.properties"));Properties properties = new Properties();properties.load(propertiesReader);//解密properties.setProperty("username", decode(properties.get("username")));properties.setProperty("password", decode(properties.get("password")));sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, properties);}1.4 優(yōu)先級
方法參數(shù)傳遞的屬性優(yōu)先級最高,次之是 resource/url 屬性中的配置,最后是 property 中的屬性。
但是在實(shí)際中最好使用 properties 文件的配置方式。
2、設(shè)置(settings)
settings 比較復(fù)雜,也很重要,它會改變 MyBatis 運(yùn)行時的行文。不配置 settings,MyBatis也可以正常工作。
大部分情況下,我們都可以不去配置 settings,或者只需修改幾個配置即可。
| 設(shè)置參數(shù) | 描述 | 有效值 | 默認(rèn)值 |
| cacheEnabled | 該配置影響的所有映射器中配置的緩存的全局開關(guān) | true | false | true |
| lazyLoadingEnabled | 延遲加載的全局開關(guān)。當(dāng)開啟時,所有關(guān)聯(lián)對象都會延遲加載。 特定關(guān)聯(lián)關(guān)系中可通過設(shè)置fetchType屬性來覆蓋該項(xiàng)的開關(guān)狀態(tài) | true | false | false |
| aggressiveLazyLoading | 當(dāng)啟用時,對任意延遲屬性的調(diào)用會使帶有延遲加載屬性的對象完整加載;反之,每種屬性將會按需加載。 | true | false | true |
| multipleResultSetsEnabled | 是否允許單一語句返回多結(jié)果集(需要兼容驅(qū)動)。 | true | false | true |
| useColumnLabel | 使用列標(biāo)簽代替列名。不同的驅(qū)動在這方面會有不同的表現(xiàn), 具體可參考相關(guān)驅(qū)動文檔或通過測試這兩種不同的模式來觀察所用驅(qū)動的結(jié)果。 | true | false | true |
| useGeneratedKeys | 允許 JDBC 支持自動生成主鍵,需要驅(qū)動兼容。 如果設(shè)置為 true 則這個設(shè)置強(qiáng)制使用自動生成主鍵,盡管一些驅(qū)動不能兼容但仍可正常工作(比如 Derby)。 | true | false | False |
| autoMappingBehavior | 指定 MyBatis 應(yīng)如何自動映射列到字段或?qū)傩浴?NONE 表示取消自動映射;PARTIAL 只會自動映射沒有定義嵌套結(jié)果集映射的結(jié)果集。 FULL 會自動映射任意復(fù)雜的結(jié)果集(無論是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
| defaultExecutorType | 配置默認(rèn)的執(zhí)行器。SIMPLE 就是普通的執(zhí)行器;REUSE 執(zhí)行器會重用預(yù)處理語句(prepared statements); BATCH 執(zhí)行器將重用語句并執(zhí)行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
| defaultStatementTimeout | 設(shè)置超時時間,它決定驅(qū)動等待數(shù)據(jù)庫響應(yīng)的秒數(shù)。 | Any positive integer | Not Set (null) |
| defaultFetchSize | Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. | Any positive integer | Not Set (null) |
| safeRowBoundsEnabled | 允許在嵌套語句中使用分頁(RowBounds)。 | true | false | False |
| mapUnderscoreToCamelCase | 是否開啟自動駝峰命名規(guī)則(camel case)映射,即從經(jīng)典數(shù)據(jù)庫列名 A_COLUMN 到經(jīng)典 Java 屬性名 aColumn 的類似映射。 | true | false | False |
| localCacheScope | MyBatis 利用本地緩存機(jī)制(Local Cache)防止循環(huán)引用(circular references)和加速重復(fù)嵌套查詢。 默認(rèn)值為 SESSION,這種情況下會緩存一個會話中執(zhí)行的所有查詢。 若設(shè)置值為 STATEMENT,本地會話僅用在語句執(zhí)行上,對相同 SqlSession 的不同調(diào)用將不會共享數(shù)據(jù)。 | SESSION | STATEMENT | SESSION |
| jdbcTypeForNull | 當(dāng)沒有為參數(shù)提供特定的 JDBC 類型時,為空值指定 JDBC 類型。 某些驅(qū)動需要指定列的 JDBC 類型,多數(shù)情況直接用一般類型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
| lazyLoadTriggerMethods | 指定哪個對象的方法觸發(fā)一次延遲加載。 | A method name list separated by commas | equals,clone,hashCode,toString |
| defaultScriptingLanguage | 指定動態(tài) SQL 生成的默認(rèn)語言。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
| callSettersOnNulls | 指定當(dāng)結(jié)果集中值為 null 的時候是否調(diào)用映射對象的 setter(map 對象時為 put)方法,這對于有 Map.keySet() 依賴或 null 值初始化的時候是有用的。注意基本類型(int、boolean等)是不能設(shè)置成 null 的。 | true | false | false |
| logPrefix | 指定 MyBatis 增加到日志名稱的前綴。 | Any String | Not set |
| logImpl | 指定 MyBatis 所用日志的具體實(shí)現(xiàn),未指定時將自動查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
| proxyFactory | 指定 Mybatis 創(chuàng)建具有延遲加載能力的對象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
3、別名(typeAliases)
?別名是一個指代的名稱。可以在 MyBatis 的上下文中使用。
在 MyBatis 中別名是不分大小寫的。
一個 typeAliases 的實(shí)例是在解析配置文件時(源碼在?XMLConfigBuilder 中)生成的,然后長期保存在 Configuration 對象中,當(dāng)我們使用它時,再把它拿出來,這樣就沒有必要運(yùn)行時再次生成它的實(shí)例了。
別名分為系統(tǒng)定義別名和自定義別名。
3.1 為什么 MyBatis 中別名是部分大小寫的
因?yàn)樵创a org.apache.ibatis.type.TypeAliasRegistry 如下:
public void registerAlias(String alias, Class<?> value) {if(alias == null) {throw new TypeException("The parameter alias cannot be null");} else {String key = alias.toLowerCase(Locale.ENGLISH);if(this.TYPE_ALIASES.containsKey(key) && this.TYPE_ALIASES.get(key) != null && !((Class)this.TYPE_ALIASES.get(key)).equals(value)) {throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + ((Class)this.TYPE_ALIASES.get(key)).getName() + "'.");} else {this.TYPE_ALIASES.put(key, value);}}}3.2 系統(tǒng)定義別名
MyBatis 自己有定義一些常用的別名,我們可以直接使用它們,不用自己定義,也不要再使用時重復(fù)定義把它們給覆蓋了。
支持?jǐn)?shù)組類型的只要加“[]”即可。比如 Integer 數(shù)組,則別名為 int[]。
| 別名 | Java類型 | 是否支持?jǐn)?shù)組 |
| _byte | byte | y |
| _long | long | y |
| _short | short | y |
| _int | int | y |
| _integer | int | y |
| _double | double | y |
| _float | float | y |
| _boolean | boolean | y |
| string | String | y |
| byte | Byte | y |
| long | Long | y |
| short | Short | y |
| int | Integer | y |
| integer | Integer | y |
| double | Double | y |
| float | Float | y |
| boolean | Boolean | y |
| date | Date | y |
| decimal | BigDecimal | y |
| bigdecimal | BigDecimal | y |
| object | Object | y |
| map | Map | n |
| hashmap | HashMap | n |
| list | List | n |
| arraylist | ArrayList | n |
| collection | Collection | n |
| iterator | Iterator | n |
| ResultSet | ResultSet | n |
?
源碼?org.apache.ibatis.type.TypeAliasRegistry 中可以看出其自定義注冊的信息,源碼如下:
public TypeAliasRegistry() {this.registerAlias("string", String.class);this.registerAlias("byte", Byte.class);this.registerAlias("long", Long.class);this.registerAlias("short", Short.class);this.registerAlias("int", Integer.class);this.registerAlias("integer", Integer.class);this.registerAlias("double", Double.class);this.registerAlias("float", Float.class);this.registerAlias("boolean", Boolean.class);this.registerAlias("byte[]", Byte[].class);this.registerAlias("long[]", Long[].class);this.registerAlias("short[]", Short[].class);this.registerAlias("int[]", Integer[].class);this.registerAlias("integer[]", Integer[].class);this.registerAlias("double[]", Double[].class);this.registerAlias("float[]", Float[].class);this.registerAlias("boolean[]", Boolean[].class);this.registerAlias("_byte", Byte.TYPE);this.registerAlias("_long", Long.TYPE);this.registerAlias("_short", Short.TYPE);this.registerAlias("_int", Integer.TYPE);this.registerAlias("_integer", Integer.TYPE);this.registerAlias("_double", Double.TYPE);this.registerAlias("_float", Float.TYPE);this.registerAlias("_boolean", Boolean.TYPE);this.registerAlias("_byte[]", byte[].class);this.registerAlias("_long[]", long[].class);this.registerAlias("_short[]", short[].class);this.registerAlias("_int[]", int[].class);this.registerAlias("_integer[]", int[].class);this.registerAlias("_double[]", double[].class);this.registerAlias("_float[]", float[].class);this.registerAlias("_boolean[]", boolean[].class);this.registerAlias("date", Date.class);this.registerAlias("decimal", BigDecimal.class);this.registerAlias("bigdecimal", BigDecimal.class);this.registerAlias("biginteger", BigInteger.class);this.registerAlias("object", Object.class);this.registerAlias("date[]", Date[].class);this.registerAlias("decimal[]", BigDecimal[].class);this.registerAlias("bigdecimal[]", BigDecimal[].class);this.registerAlias("biginteger[]", BigInteger[].class);this.registerAlias("object[]", Object[].class);this.registerAlias("map", Map.class);this.registerAlias("hashmap", HashMap.class);this.registerAlias("list", List.class);this.registerAlias("arraylist", ArrayList.class);this.registerAlias("collection", Collection.class);this.registerAlias("iterator", Iterator.class);this.registerAlias("ResultSet", ResultSet.class);} View Code3.3 自定義別名
(1)在配置文件中寫法如下
<!--定義別名--><typeAliases><typeAlias type="com.yule.user.entity.User" alias="user"/></typeAliases>(2)或者當(dāng)實(shí)體類較多的時候,使用自動掃描的形式自定義別名
<!--定義別名--><typeAliases> <package name="com.yule.user.entity"/></typeAliases>同時也可以在實(shí)體類上使用注解 @Alias
@Alias("user") public class User {//do somethings }注意:如果配置了包掃描的路徑,那么沒有在實(shí)體上加注解 @Alias 的類也在裝載在 MyBatis 的上下文中,只是 MyBatis 將類名的第一個字母變?yōu)樾?#xff0c;作為 MyBatis 上下文中的別名,所以要特別注意避免重名的情況,建議使用部分包名+類名的限定。
?
轉(zhuǎn)載于:https://www.cnblogs.com/yuxiaole/p/9463120.html
總結(jié)
以上是生活随笔為你收集整理的深入理解MyBatis的原理(三):配置文件(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Bootstrap4 导航栏元素居右
- 下一篇: SpringBoot24 SpringD