MyBatis 是一個優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。
在 MyBatis 中,數據源(DataSource)是一個非常重要的組件,它負責管理與數據庫的連接。本文將深入探討 MyBatis3 是如何獲取數據源的。
在 MyBatis 的配置文件中,數據源是通過 <dataSource> 標簽來配置的。MyBatis 支持多種類型的數據源,包括 UNPOOLED、POOLED 和 JNDI。以下是一個典型的配置示例:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
在這個配置中,<dataSource> 標簽的 type 屬性指定了數據源的類型,POOLED 表示使用連接池的數據源。<property> 子標簽則用于配置數據源的具體參數,如數據庫驅動、連接 URL、用戶名和密碼等。
MyBatis 在啟動時會解析配置文件,并根據配置創建相應的數據源。數據源的創建過程主要發生在 org.apache.ibatis.session.Configuration 類中。具體來說,Configuration 類會調用 org.apache.ibatis.datasource.DataSourceFactory 接口的實現類來創建數據源。
DataSourceFactory 接口有兩個主要的實現類:UnpooledDataSourceFactory 和 PooledDataSourceFactory。這兩個類分別用于創建非池化和池化的數據源。
UnpooledDataSourceFactory 用于創建非池化的數據源。它的實現非常簡單,主要是在 setProperties 方法中設置數據源的屬性,并在 getDataSource 方法中返回一個 UnpooledDataSource 實例。
public class UnpooledDataSourceFactory implements DataSourceFactory {
private UnpooledDataSource dataSource;
public UnpooledDataSourceFactory() {
this.dataSource = new UnpooledDataSource();
}
@Override
public void setProperties(Properties properties) {
// 設置數據源屬性
}
@Override
public DataSource getDataSource() {
return dataSource;
}
}
PooledDataSourceFactory 用于創建池化的數據源。它的實現與 UnpooledDataSourceFactory 類似,只是在 getDataSource 方法中返回一個 PooledDataSource 實例。
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
public PooledDataSourceFactory() {
this.dataSource = new PooledDataSource();
}
}
在 MyBatis 中,數據源的獲取主要通過 org.apache.ibatis.session.SqlSessionFactory 接口的實現類 org.apache.ibatis.session.defaults.DefaultSqlSessionFactory 來完成。DefaultSqlSessionFactory 在初始化時會從 Configuration 對象中獲取數據源,并將其保存在 environment 屬性中。
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
}
在 openSessionFromDataSource 方法中,environment.getDataSource() 方法用于獲取數據源。environment 是 Configuration 對象中的一個屬性,它包含了數據源、事務工廠等信息。
在 MyBatis 中,數據源主要用于獲取數據庫連接。當執行 SQL 語句時,MyBatis 會從數據源中獲取一個連接,并在執行完畢后將連接返回到連接池中(如果使用的是池化的數據源)。
public class SimpleExecutor extends BaseExecutor {
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
}
protected Connection getConnection(Log statementLog) throws SQLException {
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
}
在 SimpleExecutor 類的 doQuery 方法中,getConnection 方法用于從事務對象中獲取數據庫連接。事務對象在初始化時會從數據源中獲取連接。
MyBatis3 中數據源的獲取過程主要分為配置、創建、獲取和使用四個步驟。通過配置文件,我們可以指定數據源的類型和參數。MyBatis 在啟動時會根據配置創建相應的數據源,并將其保存在 Configuration 對象中。在執行 SQL 語句時,MyBatis 會從數據源中獲取數據庫連接,并在執行完畢后將連接返回到連接池中。
通過本文的分析,我們可以更好地理解 MyBatis3 中數據源的獲取機制,這對于我們深入理解 MyBatis 的工作原理以及進行性能優化都具有重要的意義。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。