要想解析源码,我们首先要知道什么是Mybatis
1.Mybatis的介绍
1.什么是Mybatis?
MyBatis是一个优秀的持久层框架,它对jdbc操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
——————————————————————————————————————————
2.持久化
持久化就是将程序的数据在持久状态和瞬时状态转化的过程
内存:断电即失
数据库(JDBC),io文件持久化。
生活:冷藏、罐头
———————————————————————————————————————————
3.持久层
Dao层、Service层、Controller层等
完成持久化工作的代码块 层界限十分明显
———————————————————————————————————————————
4.为什么需要Mybatis?
帮助程序员将数据存入到数据库中。
方便:
传统的JDBC代码太复杂了。简化、框架、自动化。
不用Mybatis也可以。更容易上手。技术没有高低之分
优点:
简单易学
灵活
可维护性高
提供xml标签,支持编写动态sql
最重要的一点就是用的人多!!!!
——————————————————————————————————————————
2.核心模块
2.1-配置解析
对xml进行解析,并转化为对应的对象信息。如mybatis-config.xml解析为配置类Configuration
2.2-----反射
对于ORM,需要经常对类的属性、对象的成员、方法进行判断赋值。而Mybatis则提供了反射模块来支持ORM的这个特性
2.3-----对象映射/绑定
负责jdbcType与java类之间的转化
2.4------语句执行
语句执行包含几个子流程
SQL解析
SQL执行
返回结果
2.5-----数据源管理
池化数据源 PooledDataSource
普通数据源 UnpooledDataSource
2.6-----事务管理
2.7-----插件
Mybatis支持自定义插件,对流程进行调整干预
2.8------日志
支持不同类型的日志实现
———————————————————————————————————————————
3 业务代码展示
DAO层的核心代码如下:
@Repository
@Mapper
public interface PriceChgDao {
PriceChg selectByPrimaryKey(Long id);
}
核心业务代码如下:
@Service
public class PriceServiceImpl implements PriceService {
@Autowired
private PriceChgDao priceChgDao;
@Override
@UseDataSource("price")
public APIResponse<PriceChg> getPriceChg(Long id) {
PriceChg priceChg = this.priceChgDao.selectByPrimaryKey(id);
return APIResponse.successResp(priceChg);
}
}
解析xml文件是XMLConfigBuilder类,调用在SqlSessionFactoryBean进行SqlSessionFactory的创建的时候
protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
Configuration configuration;
XMLConfigBuilder xmlConfigBuilder = null;
if (this.configLocation != null) {
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
configuration = xmlConfigBuilder.getConfiguration();
} else {
if (logger.isDebugEnabled()) {
logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
}
configuration = new Configuration();
configuration.setVariables(this.configurationProperties);
}
}
核心方法,解析xml转化为Configuration
if (xmlConfigBuilder != null) {
try {
xmlConfigBuilder.parse();
if (logger.isDebugEnabled()) {
logger.debug("Parsed configuration file: '" + this.configLocation + "'");
}
} catch (Exception ex) {
throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
} finally {
ErrorContext.instance().reset();
}
}
我们进入xmlConfigBuilder的parse()方法查看一下:
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
propertiesElement(root.evalNode("properties")); //issue #117 read properties first
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
settingsElement(root.evalNode("settings"));
environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
基本解析就在这些的方法里面,就不在更进一步的解析了,这个时候configuration关于配置文件基本初始化完毕。