<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 1. 屬性 (最先解析,供後續引用) -->
<properties resource="jdbc.properties" />
<properties url="https://config-center/props" />
<property name="custom.key" value="value" />
<!-- 2. 全局設置 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="true"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="defaultExecutorType" value="REUSE"/>
<setting name="defaultStatementTimeout" value="30"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
<!-- 3. 類型別名 -->
<typeAliases>
<!-- 單個 -->
<typeAlias alias="User" type="com.example.model.User"/>
<!-- 批量掃描包 (別名默認類名首字母小寫) -->
<package name="com.example.model"/>
<package name="com.example.dto"/>
</typeAliases>
<!-- 4. 類型處理器 -->
<typeHandlers>
<!-- 單個註冊 -->
<typeHandler handler="com.example.handler.JsonTypeHandler" javaType="com.example.model.JsonData"/>
<!-- 批量掃描 -->
<package name="com.example.handler"/>
</typeHandlers>
<!-- 5. 對象工廠/插件/其他 -->
<objectFactory type="com.example.factory.CustomObjectFactory"/>
<plugins>
<plugin interceptor="com.example.plugin.PageInterceptor">
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*Page.*"/>
</plugin>
</plugins>
<!-- 6. 環境 (多環境支持,default 指定當前) -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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}"/>
<property name="poolMaximumActiveConnections" value="20"/>
<property name="poolMaximumIdleConnections" value="10"/>
<property name="poolMaximumCheckoutTime" value="20000"/>
<property name="poolTimeToWait" value="20000"/>
<property name="poolPingEnabled" value="true"/>
<property name="poolPingQuery" value="SELECT 1"/>
<property name="poolPingConnectionsNotUsedFor" value="300000"/>
</dataSource>
</environment>
<environment id="production">
<transactionManager type="JDBC"/>
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/myapp"/>
</dataSource>
</environment>
</environments>
<!-- 7. 映射器 (最後加載,依賴前面所有配置) -->
<mappers>
<!-- 資源路徑 (相對類路徑) -->
<mapper resource="mapper/UserMapper.xml"/>
<!-- URL -->
<mapper url="file:///var/mappers/OrderMapper.xml"/>
<!-- 接口類 (需同名 XML 在同目錄) -->
<mapper class="com.example.mapper.UserMapper"/>
<!-- 批量掃描包 (接口+XML同名同目錄) -->
<package name="com.example.mapper"/>
</mappers>
</configuration>
<properties> 內部定義的 <property> (最低)resource 引用的文件 (類路徑)url 引用的遠程配置SqlSessionFactory 時傳入的 Properties 參數 (最高,覆蓋前者)
最佳實踐:敏感配置 (密碼) 用環境變量/配置中心注入,jdbc.properties 僅存非敏感默認值。
| 設置名 | 默認值 | 建議生產值 | 說明 |
|---|---|---|---|
| mapUnderscoreToCamelCase | false | true | 自動映射下劃線列名到駝峰屬性 (user_name → userName) |
| cacheEnabled | true | true | 全局二級緩存開關 |
| lazyLoadingEnabled | false | true | 開啟延遲加載 (關聯查詢按需加載) |
| aggressiveLazyLoading | true (3.4.1+ false) | false | true 時調用任意 getter 觸發全量加載,false 僅調用目標關聯屬性觸發 |
| multipleResultSetsEnabled | true | true | 支持存儲過程多結果集 |
| useColumnLabel | true | true | 用列標籤而非列名 (兼容性更好) |
| useGeneratedKeys | false | true | INSERT 後自動回填自增主鍵 |
| autoMappingBehavior | PARTIAL | PARTIAL | FULL 會自動映射嵌套結果集,可能導致 N+1 |
| defaultExecutorType | SIMPLE | REUSE | REUSE 重用 PreparedStatement,批量操作性能更好 |
| defaultStatementTimeout | 未設置 (無限) | 30 (秒) | 防止慢 SQL 佔用連接池 |
| defaultFetchSize | 未設置 (驅動默認) | 100 | 結果集分批獲取,減少內存壓力 |
| safeRowBoundsEnabled | false | false | true 允許 RowBounds 在嵌套查詢中工作 (性能差) |
| localCacheScope | SESSION | SESSION | STATEMENT 會禁用一級緩存,僅用於特殊場景 |
| jdbcTypeForNull | OTHER | OTHER | null 參數的 JDBC 類型,某些驅動需指定 (如 Oracle NULL -> NULL TYPE) |
<package name="com.example.model"/> 掃描包下所有類UserInfo → userInfo)@Alias("customName") 註解顯式指定Outer$Inner → outer$Inner (不推薦),請用靜態內部類或獨立類// 例: JSON 字符串 <-> JsonData 對象 (PostgreSQL jsonb / MySQL json)
@MappedTypes(JsonData.class)
@MappedJdbcTypes(JdbcType.VARCHAR) // 或 OTHER
public class JsonTypeHandler extends BaseTypeHandler {
private final ObjectMapper mapper = new ObjectMapper();
@Override
public void setNonNullParameter(PreparedStatement ps, int i, JsonData parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, mapper.writeValueAsString(parameter));
}
@Override
public JsonData getNullableResult(ResultSet rs, String columnName) throws SQLException {
String json = rs.getString(columnName);
return json != null ? mapper.readValue(json, JsonData.class) : null;
}
@Override
public JsonData getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getNullableResult(rs, rs.getMetaData().getColumnLabel(columnIndex));
}
@Override
public JsonData getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getNullableResult(cs, cs.getMetaData().getColumnLabel(columnIndex));
}
}
註冊:<typeHandler handler="com.example.handler.JsonTypeHandler"/> 或包掃描。
<environments default="development"> 指定默認環境SqlSessionFactory 時可覆蓋:new SqlSessionFactoryBuilder().build(inputStream, "production", props)SqlSessionFactoryBean 完全接管,environments 失效,改用 Spring DataSource、PlatformTransactionManager、PropertyPlaceholderConfigurer。<package name="com.example.mapper"/> (約定優於配置,接口+XML同名同目錄)<mapper class="..."/> (單獨註冊,需 XML 同名同目錄)<mapper resource="..."/> (舊項目、XML 與接口分離)<mapper url="..."/> (外部化映射文件)# application.yml
mybatis:
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
lazy-loading-enabled: true
aggressive-lazy-loading: false
default-executor-type: REUSE
default-statement-timeout: 30
default-fetch-size: 100
type-aliases-package: com.example.model,com.example.dto
type-handlers-package: com.example.handler
mapper-locations: classpath*:mapper/**/*.xml # 支持通配符、多模塊
# 環境由 Spring DataSource 決定,無需 environments
| 現象 | 原因 | 解決 |
|---|---|---|
| 別名衝突導致映射錯誤 | 不同包下同名類,默認別名相同 | 加 @Alias("唯一名") 或改用全限定名 |
| TypeHandler 不生效 | 未註冊、或 javaType/jdbcType 不匹配 | 檢查 @MappedTypes/@MappedJdbcTypes、包掃描路徑 |
| 延遲加載失效 / N+1 問題 | aggressiveLazyLoading=true、或未開啟 lazyLoadingEnabled | 設置 lazyLoadingEnabled=true, aggressiveLazyLoading=false |
| 自增主鍵回填失敗 | useGeneratedKeys=false、或數據庫不支持 (Oracle 需 Sequence) | MySQL/PostgreSQL/H2 開啟 true;Oracle 用 <selectKey> |
| PreparedStatement 洩漏 | defaultExecutorType=SIMPLE、長事務未提交 | 改 REUSE、檢查連接池泄漏、設置 statementTimeout |
SqlMapConfig.xml 是 MyBatis 的「總控制台」。掌握**加載順序、Properties 優先級、Settings 開關矩陣、TypeAliases/Handlers 掃描規則、Environments 多環境、Mappers 加載策略**,即可駕馭複雜配置場景。**Spring Boot 項目建議棄用 XML,全面轉向 YAML 配置**,僅保留 Mapper XML 文件,簡潔且類型安全。