Mybatis3源码分析(一):从sqlSession说起
来源:互联网 发布:199it大数据工具导航 编辑:程序博客网 时间:2024/05/17 04:56
分析MyBatis3的源码首先得从sqlSessionFactory开始,先来看一段spring配置文件中Mybaits的sqlSessionFactory的配置。
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:configuration.xml"></property> <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml"/> <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" /> </bean><bean id="blogMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.tiantian.mybatis.mapper.BlogMapper" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
spring会调用sqlSessionFactory的无参构造函数创建实例,并将dataSource和映射文件路径注入进去初始化sqlSessionFactory。这里的SqlSessionFactoryBean的实现依赖于mybatis社区自行开发的支持包,我们来看看它是怎么读取xml配置文件创建sessionFactory的:
protected SqlSessionFactory buildSqlSessionFactory() throws IOException { //代表配置的对象 Configuration configuration; //xml配置创建者 XMLConfigBuilder xmlConfigBuilder = null; //spring中注入的配置文件路径,如果不存在使用默认配置 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); } //如果配置了objectFactory使用此配置类 if (this.objectFactory != null) { configuration.setObjectFactory(this.objectFactory); } //同上 if (this.objectWrapperFactory != null) { configuration.setObjectWrapperFactory(this.objectWrapperFactory); } //如果配置了typeAliases(实体类别名标签)的基包则不用在configuration文件中配置 if (hasLength(this.typeAliasesPackage)) { String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeAliasPackageArray) { configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType); if (logger.isDebugEnabled()) { logger.debug("Scanned package: '" + packageToScan + "' for aliases"); } } } //如果是直接配置的实体类别名则在配置对象中注册 if (!isEmpty(this.typeAliases)) { for (Class<?> typeAlias : this.typeAliases) { configuration.getTypeAliasRegistry().registerAlias(typeAlias); if (logger.isDebugEnabled()) { logger.debug("Registered type alias: '" + typeAlias + "'"); } } } //是否配置mybaits的一些插件 if (!isEmpty(this.plugins)) { for (Interceptor plugin : this.plugins) { configuration.addInterceptor(plugin); if (logger.isDebugEnabled()) { logger.debug("Registered plugin: '" + plugin + "'"); } } } //是否配置typeHandler的基包 if (hasLength(this.typeHandlersPackage)) { String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeHandlersPackageArray) { configuration.getTypeHandlerRegistry().register(packageToScan); if (logger.isDebugEnabled()) { logger.debug("Scanned package: '" + packageToScan + "' for type handlers"); } } } //是否直接配置了typeHandler if (!isEmpty(this.typeHandlers)) { for (TypeHandler<?> typeHandler : this.typeHandlers) { configuration.getTypeHandlerRegistry().register(typeHandler); if (logger.isDebugEnabled()) { logger.debug("Registered type handler: '" + typeHandler + "'"); } } } //如果xmlConfigBuilder存在则开始分析创建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(); } } //事务工厂是否配置 if (this.transactionFactory == null) { this.transactionFactory = new SpringManagedTransactionFactory(); } //设置Configuration的环境对象 Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource); configuration.setEnvironment(environment); if (this.databaseIdProvider != null) { try { configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); } catch (SQLException e) { throw new NestedIOException("Failed getting a databaseId", e); } } //是否配置mapperLocations,如果存在解析创建这些mapper,mapper是mybaits管理各种sql的容器 if (!isEmpty(this.mapperLocations)) { for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments()); xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); } finally { ErrorContext.instance().reset(); } if (logger.isDebugEnabled()) { logger.debug("Parsed mapper file: '" + mapperLocation + "'"); } } } else { if (logger.isDebugEnabled()) { logger.debug("Property 'mapperLocations' was not specified or no matching resources found"); } } //创建sqlSessionFactoryBean return this.sqlSessionFactoryBuilder.build(configuration); }
从mybatis创建sqlSessionFactoryBean的过程可以看出,mybaits默认使用spring的事务管理功能或者由第三方实现,它自身并没有提供事务管理能力。其次,它拥有跟其它框架差不多的解析xml过程,都是将xml解析成一个Configuration对象随时取用。到这里我们就得到了一个sqlSessionFactoryBean对象(实际是mybatis本身的DefaultSqlSessionFactory对象),我们可以在DAO中注入这个对象并利用openSession的方法获取SqlSession对象从而进行各种数据库操作。
0 0
- Mybatis3源码分析(一):从sqlSession说起
- SpringMVC源码分析(一)从配置文件说起
- Mybatis3源码分析(09)-SqlSession创建及简要说明
- MyBatis3.3.0文档学习总结(三) --sqlSession深入源码
- SpringMVC源码分析(二)从框架设计说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- SpringMVC源码剖析(一)- 从抽象和接口说起
- Oracle使用游标删除所有用户数据表中的所有记录脚本
- 安迪的第一个字典
- 黑马程序员Android第55期——tomcat与web程序结构与Http协议
- ORM framework源码分析:引言之Java JDBC
- MiniDLNA 1.1.4 添加对rmvb格式的支持
- Mybatis3源码分析(一):从sqlSession说起
- ssh socket转发代理
- php函数serialize()与unserialize()
- innodb_lock_wait_timeout
- fedora14-yum源的配置使用详解-zz150122
- MySQL 事务没有提交导致 锁等待 Lock wait timeout exceeded
- MDS图示聚类结果
- mac下android studio打不开sdk manage
- MySQL 死锁导致无法查询解决