阅读 6620

玩转MyBatis的xml配置 | MyBatis系列(三)


「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!


相关文章

MyBatis系列汇总:MyBatis系列


前言

  • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

  • 下面我们会跟着官方文档配置实际代码来走一遍必须要掌握的配置功能和一些必须了解的配置功能!

  • 官方文档

  • 前置条件请看前面的几篇文章,本章所有内容的演示都是基于前面文章的基础之上。

  • 重点:

    • image-20210706100245597.png

一、环境配置( environments)

  • MyBatis 可以配置成适应多种环境

  • 不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

  • Mybatis 默认的事务管理器是JDBC,连接池:POOLED

  • 多环境配置(实际开发中都是以这种方式来的)

    • ContextAplication.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文件一般我们放在resources目录下 -->
            <properties resource="application.properties">
            </properties>
        
            <environments default="prod">
                <!--设置默认的环境为开发环境  -->
                <environment id="development">
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="${dev.driver}"/>
                        <property name="url" value="${dev.url}"/>
                        <property name="username" value="${dev.username}"/>
                        <property name="password" value="${dev.password}"/>
                    </dataSource>
                </environment>
                <!--测试环境用  -->
                <environment id="pre">
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="${pre.driver}"/>
                        <property name="url" value="${pre.url}"/>
                        <property name="username" value="${pre.username}"/>
                        <property name="password" value="${pre.password}"/>
                    </dataSource>
                </environment>
                <!--生产环境用  -->
                <environment id="prod">
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="${prod.driver}"/>
                        <property name="url" value="${prod.url}"/>
                        <property name="username" value="${prod.username}"/>
                        <property name="password" value="${prod.password}"/>
                    </dataSource>
                </environment>
            </environments>
            <mappers>
                <mapper resource="com/dy/mapper/UserMapper.xml"/>
            </mappers>
        </configuration>
        复制代码
    • application.properties:

      • dev.driver = com.mysql.jdbc.Driver
        dev.url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
        dev.username = root
        dev.password = 123456
        
        pre.driver = com.mysql.jdbc.Driver
        pre.url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
        pre.username = root
        pre.password = 123456
        
        prod.driver = com.mysql.jdbc.Driver
        prod.url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
        prod.username = root
        prod.password = 123456
        复制代码
      • 这个也是根据实际开发的需求来的,一般我们都是三套环境

        • dev 开发环境
        • pre 上线前转测环境
        • pro 线上环境
    • 整体目录结构如图:

      • image-20210706141920964.png
    • 这种方式可以让我们灵活的变换不同的配置文件!十分方便和简洁!

    • 这里的 ${url} 动态属性替换下面详解

二、属性(properties)

①、外部动态替换

  • 先看下本来的配置文件

    • image-20210706110700351.png
  • 实际开发中我们可能是多个环境,如:dev(开发环境)、pre(准测环境)、prod(线上环境)

    • 这可能会导致我们需要配置多个ContextAplication.xml核心配置文件,这种做法不可取。
    • Mybatis提供了动态配置替换的功能。
  • 使用如下:

    • 新建配置文件:application.properties

    • driver = com.mysql.jdbc.Driver
      url = jdbc:mysql://IP地址:3306/master?useSSL=false&amp;jeuc_2_1?useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;testOnBorrow=true
      username = root
      password = 123456
      复制代码
    • image-20210706111926683.png

    • ContextAplication.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="application.properties">
          </properties>
      
          <environments default="development">
              <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>
          </environments>
          <mappers>
              <mapper resource="com/dy/mapper/UserMapper.xml"/>
          </mappers>
      </configuration>
      
      复制代码
    • 对应关系:

    • image-20210706112336461.png

    • 好处:

      • 多环境配置可以ContextAplication.xml无需修改
      • 只需要配置application.properties文件,在实际开发中我们也是这样做的!
      • 方便测试和开发!
    • 执行结果成功:

      • image-20210706112527688.png

    ②、内部动态替换

    • 内部动态替换效果是一样的,但是没有外部配置文件的方式灵活!建议使用外部配置文件来进行灵活动态替换!
      • image-20210706112614626.png
    • 如果两种同时有呢?
      • image-20210706113812629.png
      • 内部密码瞎写是错误的,执行查看结果正常
      • 结论:优先走外面的properties文件
      • image-20210706113824879.png

    ③、方法中传入替换

    • SqlSessionFactoryBuilder.build() 方法中传入属性值

    • 我们可以先看下build这个方法的代码:

      • image-20210706114656985.png

      • image-20210706114737808.png

      • 可以看出来,可以传入inputStrem、envirnoment、properties等参数值。

        • inputStrem:字节流,这个没啥好说的,创建SqlSessionFactory必传的东西
        • envirnoment:指定的环境,跟** **保持中的id一致
        • properties:properties配置文件的设置
      • 具体案例如下:

        • Properties properties=new Properties();
                     //用的是磁盘符的绝对路径
                     InputStream input = new BufferedInputStream(new FileInputStream("D:\\workSpace\\dyj-MyBatis-Project\\MyBatis-01-properties\\src\\main\\resources\\application.properties"));
                     //加载到properties中
                     properties.load(input);
                     String resource = "ContextAplication.xml";
                     InputStream inputStream = Resources.getResourceAsStream(resource);
                     sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"prod",properties);
          复制代码
        • 打个断点瞅瞅:可以看见,properties文件成功被读取,所有数值都一样!

        • image-20210706142932738.png

  • 如果三种动态替换同时存在呢?顺序如下:

    • 首先读取在 properties 元素体内指定的属性。
    • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
    • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

④、占位符

  • 从 MyBatis 3.4.2 开始,可以为占位符指定一个默认值。

  • 前提条件:这个特性默认是关闭的。要启用这个特性,需要添加一个特定的属性来开启这个特性:

    • <properties resource="application.properties">
              <!-- 启用默认值特性 -->
              <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
          </properties>
      复制代码
  • 语法格式如下:

    •  <!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 '123456' -->
      复制代码
    •         <environment id="prod">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="${prod.driver}"/>
                      <property name="url" value="${prod.url}"/>
                      <property name="username" value="${prod.username}"/>
                      <property name="password" value="${prod.password:123456}"/>
                  </dataSource>
              </environment>
      复制代码
    • 测试看看结果:

      • 去除所有关于密码的设置
      • image-20210706144045168.png
      • 执行结果如下:成功!
        • image-20210706144011705.png

三、设置(settings)

  • 此内容不作重点讲解,了解基本概念即可!

  • 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。true | falsetrue
useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。true | falsetrue
useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARNFAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeout设置超时时间,它决定数据库驱动等待数据库响应的秒数。任意正整数未设置 (null)
defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
defaultResultSetType指定语句默认的滚动策略。(新增于 3.5.2)FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置)未设置 (null)
safeRowBoundsEnabled是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
safeResultHandlerEnabled是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true | falseFalse
localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSION | STATEMENTSESSION
jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。OTHER
lazyLoadTriggerMethods指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
defaultScriptingLanguage指定动态 SQL 生成使用的默认脚本语言。一个类型别名或全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或全限定类名。org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。true | falsefalse
returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)true | falsefalse
logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
proxyFactory指定 Mybatis 创建可延迟加载对象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true | falsetrue
configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)一个类型别名或完全限定类名。未设置
shrinkWhitespacesInSql从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5)true | falsefalse
defaultSqlProviderTypeSpecifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted.A type alias or fully qualified class nameNot set

四、别名(typeAliases)

①、typeAlias

  • 语法格式如下:

    •     <typeAliases>
              <typeAlias type="com.dy.pojo.User" alias="hello"></typeAlias>
          </typeAliases>
      复制代码
    • type:实体类的具体位置

    • alias:设置别名

  • mapper.xml

    • <select id="getUserInfo" resultType="hello">
         select * from user
      </select>
      复制代码
    • resultType:写上面设置的别名

  • 执行结果:

  • image-20210706152823904.png

  • 使用场景:

    • 实体类比较少的时候使用typeAlias
    • 当这样配置时,hello 可以用在任何使用 hello 的地方。

②、package

  • 语法格式如下:

    •     <typeAliases>
              <package name="com.dy.pojo"/>
          </typeAliases>
      复制代码
    • package:只需要指定到实体类所在目录即可,该包下的所有实体类名称的名字即是别名

  • mapper.xml

    •     <select id="getUserInfo" resultType="User">
              select * from user
          </select>
      复制代码
    • resultType:直接写实体类的名称即可

  • 执行结果

  • image-20210706152823904.png

  • 使用场景:

    • 实体类多使用 package
    • 第一种可以自定义,第二则不行,本身的名称即是它的别名,不区分大小写!

③、注解

  • 使用注解为实体类标明别名

  • 这个需要搭配着package来一起使用,当没有注解起别名时,本身名称就是别名

  • 当有@Alias("dayu")时,dayu就是它的别名

  • 语法格式如下:

    • @Alias("dayu")
      复制代码
  • mapper.xml

    •     <select id="getUserInfo" resultType="dayu">
              select * from user
          </select>
      复制代码
    • resultType:别名

  • 执行结果如下:

  • image-20210706152823904.png

  • 使用场景:

    • 我们一般搭配着 package 来一起使用
  • 下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

  • 别名映射的类型
    _bytebyte
    _longlong
    _shortshort
    _intint
    _integerint
    _doubledouble
    _floatfloat
    _booleanboolean
    stringString
    byteByte
    longLong
    shortShort
    intInteger
    integerInteger
    doubleDouble
    floatFloat
    booleanBoolean
    dateDate
    decimalBigDecimal
    bigdecimalBigDecimal
    objectObject
    mapMap
    hashmapHashMap
    listList
    arraylistArrayList
    collectionCollection
    iteratorIterator

五、映射器(mappers)

  • 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。

    ①、resource(使用相对于类路径的资源引用)

    • 语法格式如下:

    • <mappers>
          <mapper resource="com/dy/mapper/UserMapper.xml"/>
      </mappers>
      复制代码
    • 推荐使用,比较稳定,省心!

    • 结果正常:

    • image-20210706152823904.png

    ②、url(使用完全限定资源定位符)

    • 语法格式如下:

    •     <mappers>
              <mapper url="file:D:\workSpace\dyj-MyBatis-Project\MyBatis-01-properties\src\main\java\com\dy\mapper\UserMapper.xml"/>
          </mappers>
      复制代码
    • 通俗来讲就是文件位置绝对路径

    • 不推荐使用!换个环境可能就得改动!比较麻烦!

    • 结果正常:

    • image-20210706152823904.png

    ③、class(使用映射器接口实现类的完全限定类名)

    • 语法格式如下:

    • <mappers>
          <mapper class="com.dy.mapper.UserMapper"/>
      </mappers>
      复制代码
    • 不推荐使用,还是有区别的,本来指定的是xml,这个指定的mapper文件

    • 接口和它的Mapper必须同名

    • 接口和他的Mapper必须在同一包下

    • 否则报错

    • image-20210706160108165.png

    • 改正后结果正常:

    • image-20210706152823904.png

    ④、name(将包内的映射器接口实现全部注册为映射器)

    • 语法格式如下:

    •     <mappers>
              <package name="com.dy.mapper"/>
          </mappers>
      复制代码
    • 不推荐使用

    • 接口和它的Mapper必须同名

    • 接口和他的Mapper必须在同一包下

    • 这个是指定到包目录下

    • 结果正常:

    • image-20210706152823904.png

六、事务管理器(transactionManager)

  • 其实这个属于environments中的内容,但是我觉得有必要拿出来单独讲一讲!

  • 这个内容我觉得了解即可,我们大部份情况下用的都是第一种JDBC

  • 但是!我们要知道有MANAGED 这么个玩意存在!(面试的时候可能会被问到哦~)

  • 在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

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

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

    • <transactionManager type="MANAGED">
        <property name="closeConnection" value="false"/>
      </transactionManager>
      复制代码
  • 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

七、配置的顺序(补充知识点)

  • 给大家分享一个好玩的东西,为啥不写在开头呢?因为只有自己试过才好玩呀!哈哈哈哈啊!

  • 将mapper的映射位置换到上面去:

  • image-20210706161614840.png

  • 报错,看提示:

  • image-20210706161643534.png

  • 总结顺序如下:

    • properties
    • settings
    • typeAliases
    • typeHandlers
    • objectFactory
    • objectWrapperFactory
    • reflectorFactory
    • plugins
    • environments
    • databaseIdProvider
    • mappers
  • 必须按照MyBatis规定的顺序来哦~否则会报错的哟!


路漫漫其修远兮,吾必将上下求索~

如果你认为i博主写的不错!写作不易,请点赞、关注、评论给博主一个鼓励吧~hahah

文章分类
后端
文章标签