MyBatis詳解3.MyBatis配置詳解

字節(jié)跳動(dòng)飛書內(nèi)推!
北京、杭州、武漢、廣州、深圳、上海,六大城市等你來(lái)投。
感興趣的朋友可以私我咨詢&內(nèi)推,也可以通過(guò)鏈接直接投遞!
海量HC,極速響應(yīng),快來(lái)和我成為同事吧。
今日頭條、抖音、Tik Tok也可以內(nèi)推~

點(diǎn)擊進(jìn)入我的博客

MyBatis詳解1.概述
MyBatis詳解2.MyBatis使用入門
MyBatis詳解3.MyBatis配置詳解
MyBatis詳解4.映射器Mapper
MyBatis詳解5.動(dòng)態(tài)SQL
MyBatis詳解6.MyBatis技術(shù)內(nèi)幕
MyBatis詳解7.插件
MyBatis詳解8.集成Spring

1 MyBatis XML配置文件層次結(jié)構(gòu)

以下的圖片展示了MyBatis的全部配置元素


MyBatis配置文件層次結(jié)構(gòu)

2 properties元素

properties是一個(gè)配置屬性的元素,讓我們能在配置文件的上下文中使用它,MyBatis提供3種配置方式。

  • property子元素。
  • properties配置文件。
  • SqlSessionFactoryBuilder使用Properties文件構(gòu)建。
property子元素
    <property name="driver" value="com.mysql.jdbc.Driver"/>
properties配置文件

一般情況下,我們會(huì)使用一個(gè)單獨(dú)的properties配置文件來(lái)配置屬性值,以方便我們?cè)诙鄠€(gè)配置文件中重復(fù)使用它們,也方便日后維護(hù)和隨時(shí)修改。我們可以通過(guò)${key}的形式,取出在配置文件中配置的值。

<configuration>
    <!-- 引入配置文件 -->
    <properties resource="datasource.properties"/>

    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- 使用配置文件中的屬性 -->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>
SqlSessionFactoryBuilder使用Properties文件構(gòu)建

出于安全考慮,properties配置文件中的賬號(hào)密碼等元素可能是加密的,這個(gè)時(shí)候就需要對(duì)加密的元素進(jìn)行處理。

    public static void func() throws Exception {
        Properties properties = new Properties();
        properties.load(Resources.getResourceAsStream("datasource.properties"));
        // 對(duì)原賬號(hào)密碼解密
        properties.setProperty("username", decode(properties.getProperty("username")));
        properties.setProperty("password", decode(properties.getProperty("password")));

        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        // SqlSessionFactoryBuilder可以使用一個(gè)InputStream和一個(gè)Properties構(gòu)建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is, properties);
    }
三種方式的優(yōu)先級(jí)

MyBatis支持的3種配置方式可能同時(shí)出現(xiàn),并且屬性還會(huì)重復(fù)配置,MyBatis將按照下面的順序來(lái)加載:

  1. 在properties元素體內(nèi)指定的屬性首先被讀取。
  2. 根據(jù) properties元素中的resource屬性讀取類路徑下屬性文件,或者根據(jù)ur屬性指定的路徑讀取屬性文件,并覆蓋已讀取的同名屬性。
  3. 讀取作為build()方法參數(shù)傳遞的屬性,并覆蓋已讀取的同名屬性。

因此,通過(guò)build()方法參數(shù)傳遞的屬性具有最高優(yōu)先級(jí),resource/url屬性中指定的配置文件
次之,最低優(yōu)先級(jí)的是 properties屬性中指定的屬性。因此,我們盡量不要使用混合的方式來(lái)定義配置,首選的方式是使用properties文件。

3 settings設(shè)置

settings(設(shè)置)在MyBatis中是最復(fù)雜的配置,它會(huì)改變 MyBatis運(yùn)行時(shí)的行為。

設(shè)置參數(shù) 描述 有效值 默認(rèn)值
cacheEnabled 該配置影響所有映射器中配置的緩存全局開關(guān) true、 false true
lazyLoadingEnabled 延遲加載的全局開關(guān),當(dāng)它開啟時(shí),所有關(guān)聯(lián)對(duì)象都會(huì)延遲加載。特定關(guān)聯(lián)關(guān)系中可通過(guò)設(shè)置fetchType屬性來(lái)覆蓋該項(xiàng)的開關(guān)狀態(tài) true、false false
aggressiveLazyLoading 當(dāng)啟用時(shí),對(duì)任意延遲屬性的調(diào)用會(huì)使帶有延遲加載屬性的對(duì)象完整加載;反之,每種屬性將會(huì)按需加載 true、 false true
multipleresultSetsEnabled 是否允許單一語(yǔ)句返回多結(jié)果集(需要兼容驅(qū)動(dòng)) true、 false true
useColumnLabel 使用列標(biāo)簽代替列名。不同的驅(qū)動(dòng)在這方面會(huì)有不同的表現(xiàn),具體可參考相關(guān)驅(qū)動(dòng)文檔或通過(guò)測(cè)試這兩種不同的模式來(lái)觀察所用驅(qū)動(dòng)的結(jié)果 true、 false true
useGeneratedKeys 允許JDBC支持自動(dòng)生成主鍵,需要驅(qū)動(dòng)兼容。如果設(shè)置為true,則這個(gè)設(shè)置強(qiáng)制使用自動(dòng)生成主鍵 true、fase false
autoMappingBehavior 指定 MyBatis應(yīng)如何自動(dòng)映射列到字段或?qū)傩裕篘ONE表示取消自動(dòng)映射、PARTIAL只會(huì)自動(dòng)映射沒有定義嵌套結(jié)果集映射的結(jié)果集、FULL會(huì)自動(dòng)映射任意復(fù)雜的結(jié)果集 NONE、 PARTIAL、FULL PARTIAL
defaultExecutorType 配置默認(rèn)的執(zhí)行器:SIMPLE是普通的執(zhí)行器、REUSE執(zhí)行器會(huì)重用預(yù)處理語(yǔ)句(prepared statements)、BATCH執(zhí)行器將重用語(yǔ)句并執(zhí)行批量更新 SIMPLE、 REUSE、SIMPLE SIMPLE
defaultStatementTimeout 設(shè)置超時(shí)時(shí)間,它決定驅(qū)動(dòng)等待數(shù)據(jù)庫(kù)響應(yīng)的秒數(shù)。當(dāng)沒有設(shè)置的時(shí)候它取的就是驅(qū)動(dòng)默認(rèn)的時(shí)間 any positive integer Not set(null)
safeRowBoundsEnabled 允許在嵌套語(yǔ)句中使用分頁(yè)(Row Bounds) true、 false False
mapUnderscoreToCamelCase 是否開啟自動(dòng)駝峰命名規(guī)則映射,即從經(jīng)典數(shù)據(jù)庫(kù)列名 A_COLUMN到經(jīng)典Java屬性名 aColumn的類似映射 true、false false
localCacheScope MyBatis利用本地緩存機(jī)制(Local Cache)防止循環(huán)引用(circular references)和加速重復(fù)嵌套查詢。默認(rèn)值為 SESSION,這種情況下會(huì)緩存一個(gè)會(huì)話中執(zhí)行的所有查詢。若設(shè)置值為STATEMENT,本地 STATEMENT會(huì)話僅用在語(yǔ)句執(zhí)行上,對(duì)相同 SqlSession的不同調(diào)用將不會(huì)共享數(shù)據(jù) SESSION、STATEMENT SESSION
jdbcTypeForNull 當(dāng)沒有為參數(shù)提供特定的JDBC類型時(shí),為空值指定JDBC類型。某些驅(qū)動(dòng)需要指定列的JDBC類型,多數(shù)情況情況直接使用一般類型即可,比如NULL、 VARCHAR、OTHER JdbcType枚舉 OTHER
lazyLoadTriggerMethods 指定對(duì)象的方法觸發(fā)一次延遲加載 如果是一個(gè)方法列表,我們則用逗號(hào)將它們隔開 equals, clone, hashCode, toString
defaultScriptingLanguage 指定動(dòng)態(tài)SQL生成的默認(rèn)語(yǔ)言 你可以配置類的別名或者類的全限定名 org....XMLDynamicLanguageRiver
callSettersOnNulls 指定當(dāng)結(jié)果集中值為null的時(shí)候是否調(diào)用映射對(duì)象的setter(map對(duì)象時(shí)為put)方法,這對(duì)于有Map.keySet()依賴或null值初始化的時(shí)候是有用的。注意基本類型是不能設(shè)置成null的 true、 false false
logPrefix 指定MyBatis增加到日志名稱的前綴 任何字符串 沒有設(shè)置
logImpl 指定 MyBatis所用日志的具體實(shí)現(xiàn),未指定時(shí)將自動(dòng)查找 SLF4J、LOG4J、JDK LOGGING、NO LOGGING 沒有設(shè)置
proxyFactory 指定MyBatis創(chuàng)建具有延遲加載能力的對(duì)象所用到的代理工具 CGLIB、JAVASSIST (3.3.0以上版本是)JAVASSIST,否則CGLIB

4 typeAliases類型命名

別名(typeAliases)是一個(gè)指代的名稱。因?yàn)槲覀冇龅降念惾薅^(guò)長(zhǎng),所以我們希望用一個(gè)簡(jiǎn)短的名稱去指代它,而這個(gè)名稱可以在MyBatis上下文中使用,在 MyBatis中別名是不分大小寫的。一個(gè) typeAliases的實(shí)例是在解析配置文件時(shí)生成的,然后長(zhǎng)期保存在 Configuration對(duì)象中,這樣就沒有必要運(yùn)行的時(shí)候再次生成它的實(shí)例了。

系統(tǒng)定義別名

通過(guò)org.apache.ibatis.type.TypeAliasRegistry可以查看所有系統(tǒng)定義的別名,主要是基本數(shù)據(jù)類型、字符串、基本數(shù)據(jù)類型數(shù)組、日期、容器類。

通過(guò)XML自定義別名

在mybatis-config.xml中通過(guò)<typeAliases>元素可以自定義別名。

    <typeAliases>
        <typeAlias type="com.ankeetc.spring.domain.UserDomain" alias="user"/>
    </typeAliases>
通過(guò)注解的方式自定義別名
    <!-- 通過(guò)package掃描包 -->
    <typeAliases>
        <package name="com.ankeetc.spring.domain"/>
    </typeAliases>
@Alias("user")
public class UserDomain {
}

當(dāng)配合上面的配置,MyBatis就會(huì)自動(dòng)掃描包,將掃描到的類裝載到上下文中。如果配置了包掃描的路徑,而沒有注解@Alias的類也會(huì)被MyBatis裝載,MyBatis會(huì)自動(dòng)把類名的第一個(gè)字母變?yōu)樾?/strong>,作為MyBatis的別名。

5 typeHandler類型處理器

MyBatis在預(yù)處理語(yǔ)句(PreparedStatement)中設(shè)置一個(gè)參數(shù)或者從結(jié)果集(ResultSet)中取出一個(gè)值時(shí),都會(huì)用注冊(cè)了的typeHandler進(jìn)行處理。typeHandler常用的配置為Java類型(javaType)、JDBC類型(jdbcType)。typeHandler的作用就是將參數(shù)從javaType轉(zhuǎn)化為 jdbcType,或者從數(shù)據(jù)庫(kù)取出結(jié)果時(shí)把jdbcType轉(zhuǎn)化為javaType。

5.1 系統(tǒng)定義的typeHandler

在org.apache.ibatis.type.TypeHandlerRegistry中MyBatis定義了很多系統(tǒng)內(nèi)部的typeHader,主要是基本類型、字符串、時(shí)間類型、枚舉類型的處理。

5.2 自定義typeHandler

繼承BaseTypeHandler或?qū)崿F(xiàn)TypeHandler

對(duì)于自定義typeHandler的要求是必須實(shí)現(xiàn)接口org.apache.ibatis.type.TypeHandler,更簡(jiǎn)單的方式是繼承已經(jīng)實(shí)現(xiàn)了該接口的實(shí)現(xiàn)類org. apache.ibatis.type.BaseTypeHandler。

確定攔截類型

可以在自定義typeHandler里用注解配置@MappedTypes@MappedJdbcTypes,也可以在<typeHandler>元素中指定。

  • @MappedTypes定義的是JavaType類型,可以指定哪些Java類型被攔截;
  • @MappedJdbcTypes定義的是JdbcType類型,取值范圍在枚舉類org.apache.ibatis.type.JdbcType中找到。
@MappedTypes(String.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class MyStringTypeHandler implements TypeHandler<String> {
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        System.out.println("MyStringTypeHandler#setParameter");
        ps.setString(i, parameter);
    }

    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        System.out.println("MyStringTypeHandler#getResult 1");
        return rs.getString(columnName);
    }

    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        System.out.println("MyStringTypeHandler#getResult 2");
        return rs.getString(columnIndex);
    }

    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        System.out.println("MyStringTypeHandler#getResult 3");
        return cs.getString(columnIndex);
    }
}
啟用自定義的typeHander
  • 可以在mybatis-config.xml里面配置,可以選擇配置一個(gè)類或者一個(gè)包。
  • 在Mapper.xml的<resultMap>直接指定typeHandler。
  • 在Mapper.xml的參數(shù)中指定typeHandler。
    <!-- 1. 在mybatis-config.xml中配置 -->
    <typeHandlers>
        <typeHandler handler="com.ankeetc.spring.type.MyStringTypeHandler"/>
    </typeHandlers>
    <!-- 2. 在Mapper.xml中resultMap元素中配置-->
    <resultMap id="BaseResultMap" type="com.ankeetc.spring.domain.UserDomain">
        <result column="name" property="name" javaType="java.lang.String" jdbcType="VARCHAR" typeHandler="com.ankeetc.spring.type.MyStringTypeHandler"/>
    </resultMap>
    <!-- 注意必須使用上面的resultMap -->
    <select id="select" resultMap="BaseResultMap" parameterType="java.lang.Long">
        SELECT * FROM tb_name WHERE id = #{id}
    </select>
    <!-- 3. 在Mapper.xml參數(shù)中配置-->
    <insert id="insert" parameterType="com.ankeetc.spring.domain.UserDomain">
        INSERT INTO tb_name (name) VALUES (#{name, jdbcType=VARCHAR, javaType=String, typeHandler=com.ankeetc.spring.type.MyStringTypeHandler})
    </insert>

5.3 枚舉類型typeHandler

MyBatis中枚舉類型的typeHandler則有自己特殊的規(guī)則,MyBatis內(nèi)部提供了兩個(gè)轉(zhuǎn)化枚舉類型的typeHandler給我們使用。

  • org.apache.ibatis.type.EnumTypeHandler:使用枚舉字符串名稱作為參數(shù)傳遞的
  • org.apache.ibatis.type.EnumOrdinalTypeHandler:使用整數(shù)下標(biāo)作為參數(shù)傳遞的

6 objectFactory對(duì)象工廠

當(dāng)MyBatis在構(gòu)建一個(gè)結(jié)果返回的時(shí)候,都會(huì)使用ObjectFactory(對(duì)象工廠)去構(gòu)建POJO,我們可以定制自己的對(duì)象工廠。MyBatis中默認(rèn)的ObjectFactory是由org.apache.ibatis.reflection.factory.DefaultObjectFactory來(lái)提供服務(wù)的。

自定義objectFactory
  1. 實(shí)現(xiàn)ObjectFactory接口,也可以通過(guò)繼承DefaultObjectFactory擴(kuò)展功能。
  2. 在mybatis-config.xml中使用<objectFactory>元素。

7 environments環(huán)境變量

配置環(huán)境可以注冊(cè)多個(gè)環(huán)境,每一個(gè)環(huán)境分為兩大部分:一個(gè)是數(shù)據(jù)庫(kù)源(dataSource)的配置,另外一個(gè)是數(shù)據(jù)庫(kù)事務(wù)(transactionManager)的配置。

7.1 概述

    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
            </dataSource>
        </environment>
    </environments>
  1. default:表示默認(rèn)使用哪個(gè)數(shù)據(jù)源
  2. id:表示數(shù)據(jù)源的名稱
  3. transactionManager的事務(wù)類型type一共有三種:JDBC,采用JDBC方式管理事務(wù),獨(dú)立編碼中我們常常使用;MANAGED,采用容器方式管理事務(wù),在JNDI數(shù)據(jù)源中常用;自定義,由使用者自定義數(shù)據(jù)庫(kù)事務(wù)管理辦法,適用于特殊應(yīng)用。
  4. property元素配置數(shù)據(jù)源的各類屬性
  5. dataSource的type屬性是提供我們對(duì)數(shù)據(jù)厙連接方式的配置:UNPOOLED(非連接池?cái)?shù)據(jù)庫(kù))、POOLED(連接池?cái)?shù)據(jù)庫(kù))、JNDI(JNDI數(shù)據(jù)源)、自定義數(shù)據(jù)源。

7.2 數(shù)據(jù)庫(kù)事務(wù)

數(shù)據(jù)庫(kù)事務(wù)是交由SqlSession去控制的,我們可以通過(guò)SqlSession提交或者回滾。在大部分的工作環(huán)境下,我們都會(huì)使用 Spring框架來(lái)控制它。

7.3 數(shù)據(jù)源

MyBatis內(nèi)部為我們提供了3種數(shù)據(jù)源的實(shí)現(xiàn)方式:

  • UNPOOLED,使用org.apache.ibatis.datasource.unpooled.UnpooledDataSource實(shí)現(xiàn)。
  • POOLED,使用org.apache.ibatis.datasource.pooled.PooledDataSource實(shí)現(xiàn)。
  • JNDI,使用org.apache.ibatis.datasource.jndi.JndiDataSourceFactory實(shí)現(xiàn)。

7.4 自定義數(shù)據(jù)源

使用自定義數(shù)據(jù)源,它必須實(shí)現(xiàn)org.apache.ibatis.datasource.DataSourceFactory接口。然后在<dataSource>中type屬性指定對(duì)應(yīng)的全限定類名。

public class MyDataSourceFactory implements DataSourceFactory {

    DataSource dataSource;

    public MyDataSourceFactory() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/test");
        druidDataSource.setUsername("root");
        dataSource = druidDataSource;
    }

    private Properties properties;

    @Override
    public void setProperties(Properties props) {
        this.properties = props;
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }
}
    <dataSource type="com.ankeetc.spring.config.MyDataSourceFactory"/>

8 databaseIdProvider數(shù)據(jù)庫(kù)廠商標(biāo)識(shí)

在相同數(shù)據(jù)庫(kù)廠商的環(huán)境下,數(shù)據(jù)庫(kù)廠商標(biāo)識(shí)沒有什么意義,在實(shí)際的應(yīng)用中使用得比較少,因?yàn)槭褂貌煌瑥S商數(shù)據(jù)庫(kù)的系統(tǒng)還是比較少的。 MyBatis可能會(huì)運(yùn)行在不同廠商的數(shù)據(jù)庫(kù)中,它為此提供一個(gè)數(shù)據(jù)庫(kù)標(biāo)識(shí),作用在于指定SQL到對(duì)應(yīng)的數(shù)據(jù)庫(kù)廠商提供的數(shù)據(jù)庫(kù)中運(yùn)行。

8.1 系統(tǒng)默認(rèn)規(guī)則

系統(tǒng)默認(rèn)規(guī)則

type="DB VENDOR"是啟動(dòng)MyBatis內(nèi)部注冊(cè)的策略器。首先 MyBatis會(huì)將你的配置讀入Configuration類里面,在連接數(shù)據(jù)庫(kù)后調(diào)用getDatabaseProductName()方法去獲取數(shù)據(jù)庫(kù)的信息,然后用我們配置的name值去做匹配來(lái)得到DatabaseId。

獲得數(shù)據(jù)庫(kù)的Id

可以用下面的代碼來(lái)獲得數(shù)據(jù)庫(kù)的Id:sqlSessionFactory. getConfiguration(). getDatabaseId()

指定數(shù)據(jù)庫(kù)廠商

可以指定SQL在哪個(gè)數(shù)據(jù)庫(kù)廠商執(zhí)行,需要在Mapper.XML中通過(guò)指定。

    <insert id="insert" parameterType="com.ankeetc.spring.domain.UserDomain" databaseId="mysql">
        INSERT INTO tb_name (name) VALUES (#{name, typeHandler=com.ankeetc.spring.type.MyStringTypeHandler})
    </insert>

8.2 自定義規(guī)則

  1. 實(shí)現(xiàn)org.apache.ibatis.mapping.DatabaseIdProvider接口
  2. 配置<databaseIdProvider>標(biāo)簽。
public class MyDatabaseIdProvider implements DatabaseIdProvider {
    private Properties properties;

    @Override
    public void setProperties(Properties p) {
        this.properties = p;
    }

    @Override
    public String getDatabaseId(DataSource dataSource) throws SQLException {
        String dbName = dataSource.getConnection().getMetaData().getDatabaseProductName();
        return this.properties.getProperty(dbName);
    }
}
    <databaseIdProvider type="MyDatabaseIdProvider">
        <property name="SQL Server" value="sqlserver"/>
        <property name="MySQL" value="mysql"/>
        <property name="DB2" value="db2"/>
        <property name="Oracle" value="oracle"/>
    </databaseIdProvider>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,217評(píng)論 0 4
  • MyBatis配置xml層次結(jié)構(gòu),而且必須注意其順序。 MyBatis官網(wǎng)中文XML映射配置文件 1.proper...
    落葉飛逝的戀閱讀 2,433評(píng)論 0 4
  • 1 Mybatis入門 1.1 單獨(dú)使用jdbc編程問(wèn)題總結(jié) 1.1.1 jdbc程序 上邊使...
    哇哈哈E閱讀 3,410評(píng)論 0 38
  • 那是一個(gè)冬天,車?yán)锍橹鴲灍煟?守了半宿工地,偶遇搞笑老漢。 文/賀立輝 這是我在一線時(shí)候的一個(gè)事兒,現(xiàn)在想起來(lái)仍頗...
    城管原創(chuàng)文學(xué)閱讀 329評(píng)論 0 0
  • 今天認(rèn)識(shí)個(gè)新朋友,就像世上的另一個(gè)自己。好高興。感覺永遠(yuǎn)有說(shuō)不完的話題,感覺什么都很合得來(lái),都恰到好處。一切安排都...
    陳北北吶閱讀 472評(píng)論 2 6

友情鏈接更多精彩內(nèi)容