Lớp Configuration trong MyBatis nằm trong package org.apache.ibatis.session, đóng vai trò là biến toàn cục chứa toàn bộ cấu hình của framework. Các thuộc tính của lớp này tương ứng trực tiếp với nội dung được khai báo trong file cấu hình XML mybatis-config.xml. Quá trình phân tích cú pháp file XML sẽ gán giá trị cho các trường tương ứng trong đối tượng Configuration.
Do file cấu hình XML có rất nhiều thành phần, lớp Configuration cũng sở hữu một số lượng lớn thuộc tính. Dưới đây là ví dụ điển hình về cấu trúc file XML mà Configuration phải xử lý:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Cấu hình thuộc tính từ file properties -->
<properties resource="db.properties">
<property name="customKey" value="customValue"/>
</properties>
<!-- Định nghĩa bí danh kiểu dữ liệu -->
<typeAliases>
<typeAlias type="com.example.entity.User" alias="User"/>
</typeAliases>
<!-- Bộ xử lý kiểu dữ liệu (thường dùng mặc định) -->
<typeHandlers></typeHandlers>
<!-- Nhà máy tạo đối tượng -->
<objectFactory type="com.example.factory.CustomObjectFactory"></objectFactory>
<!-- Plugin can thiệp -->
<plugins>
<plugin interceptor="com.example.interceptor.SqlLogInterceptor"></plugin>
</plugins>
<!-- Các thiết lập toàn cục -->
<settings>
<setting name="cacheEnabled" value="false"/>
<setting name="useGeneratedKeys" value="true"/>
<setting name="defaultExecutorType" value="REUSE"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="defaultStatementTimeout" value="30"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="NULL"/>
<setting name="logImpl" value="SLF4J"/>
</settings>
<!-- Cấu hình môi trường -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="secret"/>
</dataSource>
</environment>
</environments>
<!-- Khai báo mapper -->
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
Các thuộc tính của lớp Configuration được thiết kế để ánh xạ trực tiếp với cấu trúc XML trên:
protected Environment environment; // Môi trường hiện tại
protected boolean safeRowBoundsEnabled = false;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase = false; // Chuyển đổi snake_case sang camelCase
protected boolean aggressiveLazyLoading = true; // Tải mạnh hay tải theo nhu cầu
protected boolean multipleResultSetsEnabled = true; // Hỗ trợ đa kết quả
protected boolean useGeneratedKeys = false;
protected boolean useColumnLabel = true;
protected boolean cacheEnabled = true; // Bật/tắt cache
protected boolean callSettersOnNulls = false;
protected boolean useActualParamName = true;
protected String logPrefix;
protected Class<? extends Log> logImpl;
protected Class<? extends VFS> vfsImpl;
protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
protected Set<String> lazyLoadTriggerMethods = new HashSet<>(
Arrays.asList("equals", "clone", "hashCode", "toString")
);
protected Integer defaultStatementTimeout;
protected Integer defaultFetchSize;
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
protected Properties variables = new Properties();
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
protected ObjectFactory objectFactory = new DefaultObjectFactory();
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
protected boolean lazyLoadingEnabled = false;
protected ProxyFactory proxyFactory = new JavassistProxyFactory();
protected String databaseId;
protected Class<?> configurationFactory;
// Các thành phần đăng ký
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();
// Bộ sưu tập các đối tượng cấu hình
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<>("Mapped Statements collection");
protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");
protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<>("Key Generators collection");
// Các tập hợp hỗ trợ quá trình phân tích
protected final Set<String> loadedResources = new HashSet<>();
protected final Map<String, XNode> sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers");
// Danh sách các thành phần chưa hoàn thiện
protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<>();
protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<>();
protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<>();
protected final Collection<MethodResolver> incompleteMethods = new LinkedList<>();
protected final Map<String, String> cacheRefMap = new HashMap<>();
Phần lớn các phương thức trong Configuration đều là getter và setter cho các thuộc tính kể trên. Quá trình khởi tạo diễn ra như sau: SqlSessionFactoryBuilder nhận luồng dữ liệu file XML, sau đó gọi phương thức parse() của XMLConfigBuilder để phân tích và trả về một đối tượng Configuration hoàn chỉnh. Đối tượng này sẽ được sử dụng xuyên suốt vòng đời của ứng dụng MyBatis, từ việc tạo SqlSession, quản lý mapper, cho đến thực thi các câu lệnh SQL.