传统JDBC
- 方式1-通过DriverManager
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, user, password);
PreparedStatement preparedStatement = connection.prepareStatement("insert into t_user (id, name) values (?, ?)");
preparedStatement.setInt(1, 12);
preparedStatement.setString(2, "this is paramter");
preparedStatement.executeUpdate();
// 如果执行的是查询,还要关闭ResultSet
// resultSet.close();
preparedStatement.close();
connection.close();
- 方式2-通过DataSource
DruidDataSource datasource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("select * from t_user");
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
int id = resultSet.getInt(1);
int gener = resultSet.getInt(2)
}
resultSet.close();
preparedStatement.close();
connection.close();
传统jdbc核心步骤说明
- 加载驱动
- 获取连接-Connection
- 获取StateMent-PreparedStatement
- 为SQL赋值-PreparedStatement.setXXX(paramterIndex, value)
- 执行SQL-PreparedStatement.executeXXX();
- 获得结果集-ResultSet
- 依次关闭各种连接-XXX.close();
Mybatis核心流程
image.png
image.png
Mybatis核心组件
Configuration MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中
SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能
Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等
ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所对应的数据类型
ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler 负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换
MappedStatement MappedStatement维护一条<select|update|delete|insert>节点的封装
SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
BoundSql 表示动态生成的SQL语句以及相应的参数信息
下面是源码断点调试图
mabatis.gif
调用案例方法链(部分)
org.apache.ibatis.binding.MapperProxy#invoke
org.apache.ibatis.binding.MapperMethod#execute
org.mybatis.spring.SqlSessionTemplate#selectList(java.lang.String, java.lang.Object)
org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke
org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
org.apache.ibatis.plugin.Plugin#invoke
com.github.pagehelper.PageInterceptor#intercept
// BaseExecutor是SimpleExecutor的基类
org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
org.apache.ibatis.executor.SimpleExecutor#doQuery
// 获取连接对象和语句对象
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
// 获取连接对象
org.apache.ibatis.executor.BaseExecutor#getConnection
org.mybatis.spring.transaction.SpringManagedTransaction#getConnection
// 根据dataSouce获取对应的Connection实例.如SpringShardingDataSouce获取ShardingConnection
org.mybatis.spring.transaction.SpringManagedTransaction#openConnection
// 从DataSource中获取ShardingConnection
org.springframework.jdbc.datasource.DataSourceUtils#fetchConnection
// 获取语句对象
org.apache.ibatis.executor.statement.RoutingStatementHandler#prepare
org.apache.ibatis.executor.statement.BaseStatementHandler#prepare
org.apache.ibatis.executor.statement.BaseStatementHandler#instantiateStatement-接口
// 获取对应的 RoutingStatementHandler是PreparedStatementHandler基类
org.apache.ibatis.executor.statement.PreparedStatementHandler#instantiateStatement
org.apache.ibatis.logging.jdbc.ConnectionLogger#invoke
com.alibaba.druid.pool.DruidPooledConnection#prepareStatement(java.lang.String)
// 设置参数
org.apache.ibatis.executor.statement.RoutingStatementHandler#parameterize
// 执行语句对象
org.apache.ibatis.executor.statement.RoutingStatementHandler#query
ps.execute();
org.apache.ibatis.logging.jdbc.PreparedStatementLogger#invoke
com.alibaba.druid.pool.DruidPooledPreparedStatement#execute
// 对结果集处理
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
MapperProxy案例说明
userMapper.queryById
UserMapper接口的quryById
MapperProxy实现UserMapper
调用UserMapper.queryById可以理解为调用了MapperProxy的queryById方法,该方法又调用了invoke方法(动态代理,无法断点到MapperProxy的queryById方法)