MyBatis总结四:配置文件xml详解

XML 映射配置文件

MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。文档的顶层结构如下:

  • configuration 配置
    • properties 属性
    • settings 设置
    • typeAliases 类型命名
    • typeHandlers 类型处理器
    • objectFactory 对象工厂
    • plugins 插件
    • environments 环境
      • environment 环境变量
        • transactionManager 事务管理器
        • dataSource 数据源
    • databaseIdProvider 数据库厂商标识
    • mappers 映射器

 

properties

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

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

 

其中的属性就可以在整个配置文件中使用来替换需要动态配置的属性值。比如:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

 

这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。

用我们之前文章里项目的文件的图解:

属性也可以被传递到 SqlSessionBuilder.build()方法中。例如:

SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);

// ... or ...

SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);

 

如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:

  • 在 properties 元素体内指定的属性首先被读取。
  • 然后会读取从类路径下资源或 properties 元素中的 url 属性(url attributes)中加载的属性,它会覆盖已读取的同名属性。
  • 最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。

因此,通过方法参数传递的属性具有最高优先级,资源文件及 url 属性配置的次之,最低优先级的是 properties 属性中指定的属性。

 

settings

调整 settings 中的设置是非常关键的,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。

常用参数:

 

设置参数描述有效值默认值
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 true | false false
aggressiveLazyLoading 当启用时,带有延迟加载属性的对象的加载与否完全取决于对任意延迟属性的调用;反之,每种属性将会按需加载。 true | false true
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true | false False

 

cacheEnabled是设置缓存的全局开关,缓存相关:缓存介绍(一级缓存,二级缓存)

 

mapUnderscoreToCamelCase 驼峰命名规则:

  骆驼式命名法就是当变量名或函数名是由一个或多个单词连结在一起,而构成的唯一识别字时,第一个单词以小写字母开始;第二个单词的首字母大写或每一个单词的首字母都采用大写字母,例如:myFirstName、myLastName,这样的变量名看上去就像骆驼峰一样此起彼伏,故得名。

那么为什么要开启自动驼峰命名映射规则呢?

下图User对象的属性userName 和 tb_user表 的字段 user_name不一致, 所以导致 用户名取出来为null

如果使用了驼峰命名映射规则,取数据的时候会自动把user_name识别成userName给实体属性赋值,这样我们写sql的时候 就不用给字段起别名来取值了

那么如何开启呢?

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

总结:解决属性名和数据库列名不一致:

1. 使用别名可以解决
2. 开启驼峰标识也可以解决

 

typeAliases

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

    <typeAliases>
        <typeAlias alias="User" type="com.zy.domain.User"/>
    </typeAliases>

这个时候我们在UserMapper.xml中可以把com.zy.domain.User替换成User了

    <select id="getUserById" parameterType="int" resultType="User">
        select * from user where id=#{id}
    </select>
    <!--查询所有用户信息-->
    <select id="getUserList" resultType="User">
        select * from user
    </select>

但是如果我们有很多Java Bean,这样也是很麻烦的,这时候我们就需要另外一种方法了,指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如: 

<typeAliases>
  <package name="com.zy.domain"/>
</typeAliases>

如此一来,只要在这个package下的Java Bean就都可以使用了。

 

普通的 Java 类型内建了许多相应的类型别名。它们都是大小写不敏感的,需要注意的是由于重载原始类型的名称所做的特殊处理。

别名映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

 

plugins 插件

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 的发行包中的源代码。假设你想做的不仅仅是监控方法的调用,那么你应该很好的了解正在重写的方法的行为。因为如果在试图修改或重写已有方法的行为的时候,你很可能在破坏 MyBatis 的核心模块。这些都是更低层的类和方法,所以使用插件的时候要特别当心。

通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定了想要拦截的方法签名即可。

// ExamplePlugin.java
@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  public Object intercept(Invocation invocation) throws Throwable {
    return invocation.proceed();
  }
  public Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }
  public void setProperties(Properties properties) {
  }
}
<!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

上面的插件将会拦截在 Executor 实例中所有的“update”方法调用,这里的 Executor 是负责低层映射语句执行的内部对象。

覆盖配置类

除了用插件来修改 MyBatis 核心行为之外,还可以通过完全覆盖配置类来达到目的。只需继承后覆盖其中的每个方法,再把它传递到 sqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会严重影响 MyBatis 的行为,务请慎之又慎。

 

environments 配置环境

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者共享相同 Schema 的多个生产数据库,想使用相同的 SQL 映射。许多类似的用例。

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

所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:

每个数据库对应一个 SqlSessionFactory 实例

为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);

如果忽略了环境参数,那么默认环境将会被加载,如下所示:

SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);

环境元素定义了如何配置环境。

  <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>

        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

注意这里的关键点:

  • 默认的环境 ID(比如:default=”development”)。
  • 每个 environment 元素定义的环境 ID(比如:id=”development”)。
  • 事务管理器的配置(比如:type=”JDBC”)。
  • 数据源的配置(比如:type=”POOLED”)。

默认的环境和环境 ID 是自我解释的。你可以使用你喜欢的名称来命名,只要确定默认的要匹配其中之一。 

 

mappers 映射器

定义 SQL 映射语句,首先我们需要告诉 MyBatis 到哪里去找到这些语句。Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用,或完全限定资源定位符,或类名和包名等。例如:

<!-- 使用项目资源路径(相对路径) -->
<mappers>
  <mapper resource="com.zy.mapper.UserMapper.xml"/>
</mappers>
<!-- 使用完全限定资源路径(绝对路径) -->
    <mappers>
        <mapper url="D:\学习\IDEAWorkSpace\mybatis01\src\main\java\com\zy\mapper\UserMapper.java"/>
    </mappers>
<!-- 指定类的全路径 **要求: 1. 目录名和包名一致(接口文件所在的路径需要和xml文件内的namespace名字一致); 2. 文件名和接口名一致.**-->
<mappers>
    <mapper class="com.zy.mapper.UserMapper"/>
</mappers>
<!-- 扫描包 **要求: 1. 目录名和包名一致; 2. 文件名和接口名一致.**-->
<mappers>
  <package name="com.zy.mapper"/>
</mappers>

 

 

posted @ 2017-04-05 22:05  青衫仗剑  阅读(588)  评论(0编辑  收藏  举报