mybaties使用过程及原理

mybaties使用过程及原理
1加载xml配置,读取bean文件,dataSource和mapper文件的位置,并返回factory对象。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(new FileInputStream(“conf/configeration.xml”));
xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="mysql.properties"></properties>
	<typeAliases>
		<package name="com.mintbao.tsp.bean"/>
	</typeAliases>
	<environments default="mysqlEnv">
		<environment id="mysqlEnv">
			<transactionManager type="JDBC">
			</transactionManager>
			<!-- <dataSource type="POOLED"> -->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
                 <property name="url" value="${jdbc.url}" />
                 <property name="username" value="${jdbc.username}" />
                 <property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
	    <mapper resource="com/mintbao/dao/accountMapper.xml" />
	</mappers>
</configuration>

biuld()方法如下:

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

2通过第一步返回的factory对象创建session对象:
SqlSession session = factory.openSession();

public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

3通过接口dao获取代理对象
AccountDao dao = session.getMapper(AccountDao.class);
创建的代理对象使用了java动态代理技术:

@SuppressWarnings("unchecked")
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

这里返回了代理对象:

 @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

下面是handler里的invoke方法,所以当你调用dao.selectAll()方法时会走到invoke方法,而在invoke方法里又调用了sqlsession的selectList()方法:

@Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
        return method.invoke(this, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }
  
public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
      case INSERT: {
    	Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
      }
      case UPDATE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
      }
      case DELETE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
      }
      case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) {
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) {
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
          result = executeForCursor(sqlSession, args);
        } else {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;
      default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      throw new BindingException("Mapper method '" + command.getName() 
          + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }

4 dao.selectAll();
调用session的selectList()方法才会去数据库连接池里拿链接,并执行底层statment的方法。

5spring集成mybaties
1在Spring.xml配置datasource

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
         	<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         	<property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&amp;characterEncoding=utf-8"/>
         	<property name="username" value="root"/>
         	<property name="password" value="root"/>
</bean> 

2创建sqlsessionFactory,把datasource传入

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         	<!-- 映射数据源 -->
         	<property name="dataSource" ref="dataSource"/>
         	<!-- 映射mybatis核心配置文件 -->
         	<property name="configLocation" value="classpath:mybatis-config.xml"/>
         	<!-- 映射mapper文件 -->
         	<property name="mapperLocations">
         		<list>
         			<value>classpath:com/bdqn/dao/**/*.xml</value>
         		</list>
         	</property>
  </bean>

3创建sqlsessiontemplete

<!-- 获得sqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
	<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

4sqlsessionTemplete可以通过getMapper()获取到代理对象。

5在sping.xml同样可以配置MapperScannerConfiger,就可以自动扫码@Mapeper注解

<!-- 配置Mapper映射器 -->
	<!-- MapperScannerConfigurer负责扫描指定包
	下面的所有Mapper映射器,然后生成符合这些映射器要求的对象
	(其实就是调用SqlSession的getMapper方法),另外还会
	将这些对象添加到spring容器里面 ,默认的id是首字母小写
	的接口名,也可以使用@Respository来设置id!-->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<!-- 这个包会自动调用mvc扫描 -->
		<!-- Mapper映射器所在的包 -->
		<property name="basePackage" value="dao"></property>
		<!-- 只扫描特定的接口 -->
		<property name="annotationClass" value="annotations.MyBatisRepository"></property>
	</bean>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值