03-配置解析 以及 生命周期作用域理解

四、配置解析

Mybatis核心配置文件

  • mybatis-config.xml系统核心配置文件
  • mybatis的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。
配置文件的层次结构(xml标签配置的顺序)

在这里插入图片描述

environments元素
<environments default="development"> default默认使用那一套运行环境
 <environment id="development">
   <transactionManager type="JDBC">
     <property name="..." value="..."/>
   </transactionManager>
   <dataSource type="POOLED">
     <property name="driver" value="${driver}"/>
     <property name="url" value="${url}"/>
     <property name="username" value="${username}"/>
     <property name="password" value="${password}"/>
   </dataSource>
 </environment>
     <!--再配置一套运行环境-->
        <environment id="test">
            <transactionManager type="">
            </transactionManager>
            <dataSource type=""></dataSource>
        </environment>
</environments>
  • environments 用来配置Mybatis的多套运行环境,将sql映射到多个不同的数据库上,必须指定其中一个为默认运行环境(使用default属性指定),MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

  • environments 子元素节点:environment

    • **environment ** 子标签:dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

      • 数据源是必须配置的。有三种内建的数据源类型 type="[UNPOOLED|POOLED|JNDI]"(不使用池,使用池,jndi)
      • unpooled:这个数据源的实现只是每次被请求时打开和关闭连接。(效率高,不实用)
      • pooled:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web 应用快速响应请求的流行处理方式。(实用)
      • jndi:这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
      • 数据源也有很多第三方的实现,比如dbcp,c3p0,druid等等…
    • **environment ** 子标签transactionManager 配置此种环境下事务类型,在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")

      • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。

      • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:

        <transactionManager type="MANAGED">
          <property name="closeConnection" value="false"/>
        </transactionManager>
        
mappers元素
  • 映射器,定义映射sql语句文件
  • 既然 MyBatis 的行为其他元素已经配置完了,我们现在就要定义 SQL 映射语句了。但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。最佳的方式是告诉 MyBatis 到哪里去找映射文件你可以使用相对于类路径的资源引用, *或完全限定资源定位符(包括 file:/// 的 URL),*或类名和包名等。映射器是MyBatis中最核心的组件之一 ,在MyBatis 3之前,只支持xml映射器,即:所有的SQL语句都必须在xml文件中配置。而从MyBatis 3开始,还支持接口映射器,这种映射器方式允许以Java代码的方式注解定义SQL语句,非常简洁。

引入资源的方法(就是告诉Mybatis mapper.xml的路径) 有多种方式

  • 使用相对于类路径的资源引用:使用resource属性,即配置文件的全路径(注意:“.”要改成“/”)

    <mappers>
     <mapper resource="com/atdk/dao/UserMapper.xml"/>
    </mappers>
    
  • 使用完全限定资源定位符(URL) 使用url属性

    <!-- 使用完全限定资源定位符(URL) -->
    <mappers>
     <mapper url="file:///var/mappers/AuthorMapper.xml"/>
    </mappers>
    
  • 使用映射器接口实现类的完全限定类名:即使用接口的包全路径:注意:需要配置文件名称和接口名称一致,并且位于同一目录下 使用class属性 此种方式但我们注解开发时,需要使用这种方式

    <!--
    使用映射器接口实现类的完全限定类名
    需要配置文件名称和接口名称一致,并且位于同一目录下
    -->
    <mappers>
    <mapper class="com.atdk.dao.UserMapper"/>
    </mappers>
    
  • 将包内的映射器接口实现全部注册为映射器:**注意:但是需要配置文件名称和接口名称一致,并且位于同一目录下,**使用packge标签替换mapper标签,使用package 的name属性指定包的路径

    <!--
    将包内的映射器接口实现全部注册为映射器
    但是需要配置文件名称和接口名称一致,并且位于同一目录下
    -->
    <mappers>
     <package name="org.mybatis.builder"/>
    </mappers>
    
Properties元素标签

数据库这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。

我们一般都会把数据的配置信息保存到properties 配置文件中,我们在Mybatis核心配置文件中可以使用Properties标签引入外部配置文件,加载配置文件的信息,environment标签中获取配置文件信息(通过${key}),此外我们在加载的配置文件之后,还可以在通过子标签property追加几个配置信息

注意: 优先级

  • 配置文件优先级的问题**,当我们外部文件配置信息和我们通过property标签定义的配置信息重复时,优先使用外部文件的配置信息,但是当外部文件发生错误时,Mybatis会自动调用我们手动配置的信息。**比如:我们配置文件中定义了一组数据username和password,我们又手动设置了一对一样的配置信息,当Mybatis按照优先级调用外部信息登录数据库时,密码或用户名不对,就会调用我们自定义的username和root再次登录, 可以说备用,防止发生错误
  • 首先读取在 properties 元素体内指定的属性。
  • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
  • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

因此,通过方法参数传递的属性具有最高优先级,

resource/url 属性中指定的配置文件次之,

最低优先级的则是 properties 元素中指定的属性。

新特性:占位符(官方原文)

从 MyBatis 3.4.2 开始,你可以为**占位符指定一个默认值。**例如:如果属性 ‘username’ 没有被配置,‘username’ 属性的值将为 ‘ut_user’

<dataSource type="POOLED">
  <!-- ... -->
  <property name="username" value="${username:ut_user}"/> <!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 'ut_user' -->
</dataSource>

**这个特性默认是关闭的。**要启用这个特性,需要添加一个特定的属性来开启这个特性。例如:

<properties resource="org/mybatis/example/config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- 启用默认值特性 -->
</properties>

提示 如果你在属性名中使用了 ":" 字符(如:db:username),或者在 SQL 映射中使用了 OGNL 表达式的三元运算符(如: ${tableName != null ? tableName : 'global_constants'}),就需要设置特定的属性来修改分隔属性名和默认值的字符。例如:

<properties resource="org/mybatis/example/config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- 修改默认值的分隔符 -->
</properties>
<dataSource type="POOLED">
  <!-- ... -->
  <property name="username" value="${db:username?:ut_user}"/>
</dataSource>

示例:

 <properties resource="dp.properties">
        <!--我们还可以加入一些属性配置在原有的外部配置文件属性上
        注意:如果两个文件有一个字段,优先使用外部配置文件的,
        比如我们添加的两个属性在外部配置文件中也有,优先使用外部配置文件的username和password
        一旦连接失败则使用我们后来添加的属性username和password
        -->
        <property name="username" value="root"/>
        <property name="password" value="12222"/>
        <!--开启默认占位符 设置为true-->
        <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
        <!-- 修改默认值的分隔符“:”变成“?:” -->
        <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/>
    </properties>ame="password" value="12222"/>
</properties>

在这里插入图片描述

<environment id="development">
    <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url"
                  value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </dataSource>
</environment>
typeAliases元素标签

类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。

  • 方式一:使用typeAlias 适合实体类比较少的时候
<typeAliases>
    <!--方式1: 给具体的一个类起一个别名 适用于实体类比较少的时候 type:写入全类名,alias写入别名-->
    <typeAlias type="com.atdk.pojo.User" alias="User"/>
</typeAliases>
  • 方式二:使用package 适合实体比较多的时候,直接扫描指定的包下所有实体类,当没有注解时,默认为所有实体类起别名为类名首字母小写
<typeAliases>
    <!--方式二:直接扫描指定的包下所有实体类,Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 适合用户实体类比较多的时候,但是我们也可以通过注解来为实体类起别名
    -->
    <package name="com.atdk.pojo"/>
</typeAliases>
  • 方式三:使用注解@Alias(别名)为JavaBean起别名

    @Alias("user")
    public class User {
      ...
    }
    

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
在这里插入图片描述
在这里插入图片描述

Setting设置标签元素
  • 设置(settings)相关 => 查看帮助文档

    • 懒加载
    • 日志实现
    • 缓存开启关闭
  • 一个配置完整的 settings 元素的示例如下:

    <settings>
      <setting name="cacheEnabled" value="true"/>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="multipleResultSetsEnabled" value="true"/>
      <setting name="useColumnLabel" value="true"/>
      <setting name="useGeneratedKeys" value="false"/>
      <setting name="autoMappingBehavior" value="PARTIAL"/>
      <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
      <setting name="defaultExecutorType" value="SIMPLE"/>
      <setting name="defaultStatementTimeout" value="25"/>
      <setting name="defaultFetchSize" value="100"/>
      <setting name="safeRowBoundsEnabled" value="false"/>
      <setting name="mapUnderscoreToCamelCase" value="false"/>
      <setting name="localCacheScope" value="SESSION"/>
      <setting name="jdbcTypeForNull" value="OTHER"/>
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
    </settings>
    
typeHandlers 类型处理器
  • 无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
  • 你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。【了解即可】
objectFactory 对象工厂
  • MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。
  • 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过有参构造方法来实例化。
  • 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。【了解即可】

Mapper.xml 映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atdk.dao.UserMapper">
   
</mapper>
  • namespace中文意思:命名空间,作用如下:

    • namespace的命名必须跟某个接口同名,用来绑定mapper接口
    • 接口中的方法与映射文件中sql语句id应该一一对应
    1. namespace和子元素的id联合保证唯一 , 区别不同的mapper
    2. 绑定DAO接口
    3. namespace命名规则 : 包名+类名

Mybatis映射语句的强大,是Mybatis的强大之处

补充:生命周期和作用域

总述:作用域(Scope)和生命周期

理解我们目前已经讨论过的不同作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。

我们可以先画一个流程图,分析一下Mybatis的执行过程!

开始–>SqlSessionFactoryBuilder 加载外部Mybatis核心配置文件获取SqlSessionFactory对象—>通过SqlSessionFactory创建SqlSession—>通过SqlSession获取 sql mapper -->结束

在这里插入图片描述

Mybatis的SqlSessionFactoryBuilder,SqlSessionFactory ,SqlSession 作用域理解和生命周期理解
  • SqlSessionFactoryBuilder 的作用在于创建 SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 SqlSessionFactory 的方法中,而不要让其长期存在。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
  • **SqlSessionFactory 可以被认为是一个数据库连接池,它的作用是创建 SqlSession 接口对象。**因为 MyBatis 的本质就是 Java 对数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个 MyBatis 的应用之中,所以一旦创建了 SqlSessionFactory,就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBatis 的应用周期。
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 **SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。**因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
  • 由于 **SqlSessionFactory 是一个对数据库的连接池,所以它占据着数据库的连接资源。**如果创建多个 SqlSessionFactory,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免发生这样的情况。
  • 因此在一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是应用作用域。
  • 如果说 SqlSessionFactory 相当于数据库连接池,那么 SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务。所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try…catch…finally… 语句来保证其正确关闭。
  • 所以 SqlSession 的最佳的作用域是请求或方法作用域。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值