Spring 集成 MyBatis

丶灬走出姿态 提交于 2020-02-27 15:19:15

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>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!