1、MyBatis代码解析
1.1 MyBatis SqlSession 创建过程
SqlSessionFactoryBean是什么?
SqlSessionFactoryBean是用来创建MyBatis的SqlSessionFactory对象的。
SqlSessionFactory是用于创建SqlSession对象的,SqlSession对象是MyBatis基本的接口,通过SqlSession对象可以执行SQL和控制事务。
进入SqlSessionFactoryBean类的代码发现其中含有afterPropertiesSet()方法。根据前面文章有关Bean生命周期的介绍,此方法会在IoC容器启动过程中,在Bean的构造器执行完后执行。afterPropertiesSet()这个方法是生成SqlSessionFactory的入口。
private SqlSessionFactory sqlSessionFactory;
@Override
public void afterPropertiesSet() throws Exception {
// 省略其他代码
this.sqlSessionFactory = buildSqlSessionFactory();
}
SqlSessionFactory(接口) ---> DefaultSqlSessionFactory(实现类)
SqlSession(接口) ---> DefaultSqlSession(实现类)
SqlSessionFactoryBean的接口定义如下图:
1.2 MyBatis MapperProxy代理对象创建过程
在MyBatis中,数据库访问层对象(DAO)是通过MapperProxy对象进行代理的,即在调用customerDao(业务数据访问接口)中的方法时,是在执行MapperProxy代理对象中的方法。下面分析MapperProxy对象的获取过程。
MapperFactoryBean类中getObject()方法将会返回代理对象(MapperProxy):
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
1.3 MyBatis SQL 执行过程
获取到MapperProxy对象后,下面将分析MapperProxy是如何运行的。
因为MapperProxy实现了InvocationHandler接口,因此其执行逻辑封装在invoke()方法中:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else if (isDefaultMethod(method)) {
return invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
以执行update为例,最后调用PreparedStatementHandler的update()如下,此处使用原生的JDBC的PreparedStatement进行数据库操作的地方。
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
2 xml的例子
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.test"/>
<!-- 引入jdbc配置文件 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
<!-- spring和MyBatis整合-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mapping.xml文件,**表示迭代查找 -->
<property name="mapperLocations">
<array>
<value>classpath:mybatis-customer-mapper.xml</value>
</array>
</property>
</bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 ,包下的类需要使用@MapperScan注解,否则容器注入会失败 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.mybatis.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
来源:oschina
链接:https://my.oschina.net/u/3777515/blog/3163743