mybatis中SqlSessionFactory和SqlSession初步探究

目前项目中大多采用springboot那一套,今天想具体了解mybatis中的工作原理。
在这里插入图片描述

mybatis中有两个主要的工作对象,一个是SqlSessionFactory,一个是SqlSession

这两者有什么关系呢?
  具体的大致步骤是这样的:

  1. 程序中预先配置mybatis的xml文件
  2. SqlSessionFactoryBuilder通过配置好的xml文件来构建SqlSessionFactory,SQLSessionFactory是线程安全的,一旦被创建,应用在执行期间都会存在
  3. SqlSessionFactory来创建SqlSession对象
  4. SqlSession是mybatis的关键对象,是应用程序与持久储存层交互的一个单线程对象(因为它是非线程安全的),sqlSession去操作sql语句(观察上面的流程图,我估计sqlSession就是去调用我们常写的mapper里的那些增删改查),使用结束之后,还需要使用finally进行关闭连接
   /*获取当前mybatis配置文件,通过Mybatis包中的Resources对象很轻松的获取到配置文件*/
   //InputStream rs = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");这种方式也    可以
   Reader rs= Resources.getResourceAsReader("mybatis-config.xml");
   /*创建sqlSessionFactory对象*/
   SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(rs);
   /*创建SQLSession对象操作持久层对象*/
   SqlSession sqlSession = sqlSessionFactory.openSession();
   sqlSession.getMapper(xxxMaper.class).getXXXList();

那接着来看,mybatis的这个预先的配置文件中应该有哪些内容呢?
 主要包括这几个方面:

  • properties:将数据库信息单独写入一个jdbc.properties文件中,方便维护
  • settings:一般设置一些全局配置参数,比如开启二级缓存,开启延迟加载等
    在这里插入图片描述
  • typeAliases:存在的意义仅在于用来减少类完全限定名的冗余
	<typeAliases> 
			<typeAlias type="com.hp.entity.member" alias="mb"/>	
	</typeAliases>

 我们在mapper文件中就可以使用它的别名:

	<select id="Login" resultType="mb"> 
	select * from userinfo where username=#{0} and password=#{1} and role=#{2};
	</select>	
  • environments、environment、dataSource
<environments default="development">
	<!--数据库配置环境1  -->
		<environment id="development">
		<transactionManager type="JDBC"/>
		<dataSource type="POOLED">
		<property name="driver" value="com.mysql.jdbc.Driver"/> 
		<property name="url" value="jdbc:mysql://localhost:3306/xxx"/> 
		<property name="username" value="root"/> 
		<property name="password" value="123456"/> 
		</dataSource>
		</environment>
		
		<!--数据库配置环境2  -->
		<environment id="release">
		<transactionManager type="JDBC"/>
		<dataSource type="POOLED">
		...
		</dataSource>
		</environment>
	</environments>

 environments default 属性来决定使用哪个数据库的配置
 DataSource 这里介绍它的几个类型,分别是UNPOOLED、POOLED和JNDI。
  UNPOOLED 它只有在每次请求的时候才打开和关闭连接。
  POOLED 利用“池”的概念将JDBC的连接对象组织起来,不需要每次请求创建新的连接实例,节约了初始化和认证时间,对于要求快速响应的程序,推荐使用这个连接池类型。
  JNDI

  • mappers:定义sql映射语句。需要告诉 MyBatis 到哪里去找到这些语句,一般两种方案:
   <mappers>
      <!--直接映射到相应的mapper文件-->
      <mapper resource="com/xhm/mapper/UserMapper.xml"/>
      <!--扫描包路径下所有xxMapper.xml文件-->
      <package name="com.xhm.mapper"/>
   </mappers>  

完整的mybatis-config.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标签用来引入外部properties文件 
            resource:引入类路径下的资源
            url:引入网络路径或者磁盘路经下的资源
    -->
    <properties resource="jdbc.properties" />
    
    <!-- 
        settings包含了很多重要的设置项
            name:项目名
            value:项目值
        可在官方的参考文档中查询
     -->
    <settings>
        <setting name="jdbcTypeForNull" value="NULL" />
        <setting name="lazyLoadingEnabled" value="true" />
        <setting name="aggressiveLazyLoading" value="false" />
    </settings>

    <typeAliases>
        <!-- 
            typeAlias为某个java类起别名
                type:指定要起别名的类的全限定名;默认别名为类名小写
                alias:自定义别名
         -->
        <typeAlias type="mytest.domain.Product" alias="product"/>
        <!-- 
            package为某个包中的所有类批量起别名(包括子包下的类,别名默认为类名小写)
                name:指定包名
        -->
        <package name="mytest.domain" />
        <!-- 在批量其别名情况下可以使用@Alias注解为特定的类自定义别名 -->
    </typeAliases>
    
    <!-- 
        environments环境配置 {default:指定环境(指定环境的id)}
        environment环境 {id:环境的唯一标识}
            transactionManager:事务管理器 {type:事务管理器类型}
            dataSource:数据源 {type:数据源类型}
    -->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}" />
                <property name="url" value="${mysql.url}" />
                <property name="username" value="${mysql.username}" />
                <property name="password" value="${mysql.password}" />
            </dataSource>
        </environment>

        <environment id="oracle">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${oracle.driver}" />
                <property name="url" value="${oracle.driver}" />
                <property name="username" value="${oracle.driver}" />
                <property name="password" value="${oracle.driver}" />
            </dataSource>
        </environment>
    </environments>
    
    <!-- 
        databaseIdProvider支持多数据库厂商
            type="DB_VENDOR":VendorDatabaseIdProvider
            作用是得到数据库厂商的标识,mybatis就能执行不同的Sql语句
     -->
    <databaseIdProvider type="DB_VENDOR">
        <!-- 为不同的数据库厂商起别名 -->
        <property name="MySQL" value="mysql" />
        <property name="Oracle" value="oracle" />
    </databaseIdProvider>

    <mappers>
        <!-- 
            mapper注册一个Sql映射
                注册映射文件
                resource:引用类路径下的sql映射文件;
                url:引用本地磁盘或网络路径的sql映射文件;
                
                注册接口
                class:引用(注册)接口
                条件:1.有sql映射文件,映射文件需要和接口同名且在同一个目录下
                    2.无sql映射文件,使用注解@Select(Sql)...写在方法上
                    
            package批量注册(class批量化,条件和class一样)
                name:批量注册指定包中的接口
         -->
        <package name="mytest.dao" />
    </mappers>
</configuration>

后面再学习的过程中,接触了ssm,那么spring中是怎么整合的mybatis的呢,通过引入了SqlSessionFactoryBean,下面来了解一下SqlSessionFactoryBean:
  SqlSessionFactoryBean来代替SqlSessionFactoryBuilder创建sqlSession。
  SqlSessionFactoryBean有一个必须属性dataSource,另外其还有一个通用属性configLocation,结合我之前写的代码:
  在这里插入图片描述
  SqlSessionFactoryBean实现了FactoryBean接口,重写了getObject接口 ,通过该方法返回SqlSessionFactory对象
  SqlSessionFactoryBean实现了InitializingBean接口,spring初始化的时候会执行实现了InitializingBean接口的afterPropertiesSet方法
  SqlSessionFactoryBean实现了ApplicationListener接口,在spring容器执行的各个阶段进行监听,SqlSessionFactoryBean实现这个接口是为了容器刷新的时候,更新sqlSessionFactory
  简单看一下入口方法afterPropertiesSet():

  @Override
  public void afterPropertiesSet() throws Exception {
    //dataSource是必须要配置的
    notNull(dataSource, "Property 'dataSource' is required");
    notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
    //configuration是bean,configLocation是配置文件,两者不能同时配置
    state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
              "Property 'configuration' and 'configLocation' can not specified with together");

    //主要逻辑都在buildSqlSessionFactory方法,创建sqlSessionFactory,getObject就是返回的sqlSessionFactory 
    this.sqlSessionFactory = buildSqlSessionFactory();
  }

  @Override
  public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }

    return this.sqlSessionFactory;
  }

  关键方法buildSqlSessionFactory(),主要包含下面几步:

  1. 构建configuration对象
  2. 设置数据源dataSource
  3. 解析configLocation
  4. 解析mapperLocations
  5. 设置其他属性
  6. 构建sqlSessionFactory对象
    具体细节下次在分析
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值