This is the seventh day of my participation in the First Challenge 2022
Introduction to the
MyBatis can connect to a Druid database in the same way as the Druid database connection pool
The source code parsing
Based on the sample code from the previous article:
public class MybatisTest {
@Test
public void test(a) {
try(SqlSession session = buildSqlSessionFactory().openSession()) {
PersonMapper personMapper = session.getMapper(PersonMapper.class);
personMapper.createTable();
personMapper.save(Person.builder().id(1L).name("1").build());
Person person = personMapper.getPersonById(1); System.out.println(person); }}public static SqlSessionFactory buildSqlSessionFactory(a) {
String JDBC_DRIVER = "org.h2.Driver";
String DB_URL = "jdbc:h2:mem:test; DB_CLOSE_DELAY=-1";
String USER = "sa";
String PASS = "";
DataSource dataSource = new PooledDataSource(JDBC_DRIVER, DB_URL, USER, PASS);
Environment environment = new Environment("Development".new JdbcTransactionFactory(), dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(PersonMapper.class);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
returnbuilder.build(configuration); }}Copy the code
Currently we want to find the part that connects to the database
From reading the book MyBatis3 Source Code In Depth, we know that the execution is in the Executor, and we keep track of the relevant code
After unremitting efforts to track, the following key code is obtained:
Found the key code to get the connection from Executor in the execution statement
public class SimpleExecutor extends BaseExecutor {
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
// Get the database connection
Connection connection = this.getConnection(statementLog);
Statement stmt = handler.prepare(connection, this.transaction.getTimeout());
handler.parameterize(stmt);
returnstmt; }}Copy the code
Continuing the trace, we come to the transaction manager defined in our example: JdbcTransactionFactory
public class JdbcTransaction implements Transaction {
public Connection getConnection(a) throws SQLException {
if (this.connection == null) {
this.openConnection();
}
return this.connection;
}
protected void openConnection(a) throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Opening JDBC Connection");
}
// Get it from DataSource
this.connection = this.dataSource.getConnection();
if (this.level ! =null) {
this.connection.setTransactionIsolation(this.level.getLevel());
}
this.setDesiredAutoCommit(this.autoCommit); }}Copy the code
PooledDataSource = PooledDataSource = PooledDataSource = PooledDataSource = PooledDataSource
public class PooledDataSource implements DataSource {
public Connection getConnection(a) throws SQLException {
return this.popConnection(this.dataSource.getUsername(), this.dataSource.getPassword()).getProxyConnection();
}
private PooledConnection popConnection(String username, String password) throws SQLException {
while(conn == null) {
synchronized(this.state) {
PoolState var10000;
if (!this.state.idleConnections.isEmpty()) {
......
} else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) {
// Get the database connection pool connection
conn = new PooledConnection(this.dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + "."); }}else{... }if(conn ! =null) {... }}}... }}Copy the code
Let’s keep going:
public class UnpooledDataSource implements DataSource {
public Connection getConnection(a) throws SQLException {
return this.doGetConnection(this.username, this.password);
}
private Connection doGetConnection(String username, String password) throws SQLException {
Properties props = new Properties();
if (this.driverProperties ! =null) {
props.putAll(this.driverProperties);
}
if(username ! =null) {
props.setProperty("user", username);
}
if(password ! =null) {
props.setProperty("password", password);
}
return this.doGetConnection(props);
}
private Connection doGetConnection(Properties properties) throws SQLException {
this.initializeDriver();
// See the familiar native way to get a database connection
Connection connection = DriverManager.getConnection(this.url, properties);
this.configureConnection(connection);
returnconnection; }}Copy the code
Here we find the key code in the source code how to get the database connection
This is essentially an encapsulation of native database operations
Call stack review
Let’s go back and look at the class call stack in the process:
- MybatisTest: our test code
- MapperProxy: the proxy class of MyBatis Mapper
- MapperMethod: related to SQL execution
- DefaultSqlSession
- CachingExecutor
- BaseExecutor
- SimpleExecutor
- JdbcTransation
- PooledDataSource
- UnpooledDataSource
As you can see, the database connection is obtained from the DataSource, and the PooledDataSource is MyBatis’ own database connection pool, which uses the unpooled UnpooledDataSource
MyBatis+Druid = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource = DataSource
conclusion
MyBatis+Druid = MyBatis+Druid = MyBatis+Druid = MyBatis+Druid = MyBatis+Druid