mybatis 一般集成到spring框架中使用,下面介绍如何在spring中使用mybatis

  1. 创建datasource实例

     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <property name="driverClassName">
             <value>com.mysql.jdbc.Driver</value>
         </property>
         <property name="url">
             <value>jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8</value>
    
         </property>
         <property name="username">
             <value>root</value>
         </property>
         <property name="password">
             <value>xxx</value>
         </property>
     </bean>
  2. 创建SqlSessionFactoryBean 实例

     <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
         <property name="dataSource" ref="dataSource"/>
         <property name="plugins">
             <array>
                 <bean class="com.learn.springmybatis.ExecutorInterceptor"></bean>
             </array>
         </property>
     </bean>
  3. 创建数据库操作的bean

     <bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
         <property name="mapperInterface" value="com.learn.springmybatis.UserDao"/>
         <property name="sqlSessionFactory" ref="sqlSession"></property>
     </bean>

    当然还有具体java代码,这里不体现出来。列出上述配置主要说明mybatis使用的大体流程。业务代码最终是拿数据库操作bean实例,如userDao去操作数据库。那我们就从userDao开始吧,看看业务代码通过mybatis是如何和db打交道的。

userDao的实例化过程

下面是UserDao的java代码,一个Interface,里面除了有一个注解,啥都没有。那么它是如何实现数据插入的呢?

public interface UserDao {

    @Insert(" insert into user ( id, name, title ) values (#{id},#{name}, #{title}) ")
    public int insert(User user);
}
  • userDao是MapperFactoryBean创建的
    从xml配置我们可以得知,userDao是MapperFactoryBean创建,而MapperFactoryBean实现类FactoryBean接口,Spring的FactoryBean可以根据需要创建不同类型的bean

    通过MapperFactoryBean的getObject获取userDao实例

      public T getObject() throws Exception {
          return this.getSqlSession().getMapper(this.mapperInterface);
      }

    this.getSqlSession()是new SqlSessionTemplate(sqlSessionFactory)
    最终进入Configuration的getMapper

      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
          return this.mapperRegistry.getMapper(type, sqlSession);
      }

    最终调用到MapperRegistry,具体代码如下,通过type在knownMappers获取mapperProxyFactory,这里直接用knownMappers,那么这个knownMapper什么时候初始化好的?先留个疑问,不着急解答。获取到mapperProxyFactory后创建新的实例

      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
          MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
          if (mapperProxyFactory == null) {
              throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
          } else {
              try {
                  return mapperProxyFactory.newInstance(sqlSession);
              } catch (Exception var5) {
                  throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
              }
          }
      }

    新实例如何创建?看代码,用到java的动态代理,sql的执行,最终会代理到这个MapperProxy进行,想知道sql如何执行,只需分析MapperProxy即可。

      protected T newInstance(MapperProxy<T> mapperProxy) {
          return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
      }
    
      public T newInstance(SqlSession sqlSession) {
          MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
          return this.newInstance(mapperProxy);
      }
  • 未完待续

ThinkFault
13 声望1 粉丝