mybatis全局配置mybatis-config.xml

  大部分时候,咱们都是在Spring 里面去集成MyBatis。由于Spring 对MyBatis 的一些操做进行的封装,咱们不能直接看到它的本质,因此先看下不使用容器的时候,也就是编程的方式,MyBatis 怎么使用。先引入mybatis jar 包。html

  首先咱们要建立一个全局配置文件,这里面是对MyBatis 的核心行为的控制,好比mybatis-config.xml。java

  第二个就是咱们的映射器文件,Mapper.xml,一般来讲一张表对应一个,咱们会在这个里面配置咱们增删改查的SQL 语句,以及参数和返回的结果集的映射关系。跟JDBC 的代码同样,咱们要执行对数据库的操做,必须建立一个会话,这个在MyBatis 里面就是SqlSession。SqlSession 又是工厂类根据全局配置文件建立的。因此整个的流程就是这样的(以下代码)。最后咱们经过SqlSession 接口上的方法,传入咱们的Statement ID 来执行SQL。这是第一种方式。sql

  这种方式有一个明显的缺点,就是会对Statement ID 硬编码,并且不能在编译时进行类型检查,因此一般咱们会使用第二种方式,就是定义一个Mapper 接口的方式。这个接口全路径必须跟Mapper.xml 里面的namespace 对应起来,方法也要跟StatementID 一一对应。数据库

public void testMapper() throws IOException {
  String resource = "mybatis-config.xml";
  InputStream inputStream = Resources.getResourceAsStream(resource);
  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  SqlSession session = sqlSessionFactory.openSession();
  try {
    BlogMapper mapper = session.getMapper(BlogMapper.class);
    Blog blog = mapper.selectBlogById(1);
    System.out.println(blog);
  } finally {
    session.close();
  }
}

  这个就是咱们单独使用MyBatis 的基本流程。apache

核心对象的生命周期

  在编程式使用的这个demo 里面,咱们看到了MyBatis 里面的几个核心对象:SqlSessionFactoryBuiler、SqlSessionFactory、SqlSession 和Mapper 对象。这几个核心对象在MyBatis 的整个工做流程里面的不一样环节发挥做用。若是说咱们不用容器,本身去管理这些对象的话,咱们必须思考一个问题:何时建立和销毁这些对象?在一些分布式的应用里面,多线程高并发的场景中,若是要写出高效的代码,必须了解这四个对象的生命周期。这四个对象的声明周期的描述在官网上面也能够找到。咱们从每一个对象的做用的角度来理解一下,只有理解了它们是干什么的,才知道何时应该建立,何时应该销毁。编程

SqlSessionFactoryBuilder

  这个类能够被实例化、使用和丢弃,一旦建立了 SqlSessionFactory,就再也不须要它了。 所以 SqlSessionFactoryBuilder 实例的最佳做用域是方法做用域(也就是局部方法变量)。 你能够重用 SqlSessionFactoryBuilder 来建立多个 SqlSessionFactory 实例,可是最好仍是不要让其一直存在,以保证全部的 XML 解析资源能够被释放给更重要的事情。缓存

SqlSessionFactory

  SqlSessionFactory 一旦被建立就应该在应用的运行期间一直存在,没有任何理由丢弃它或从新建立另外一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复建立屡次,屡次重建 SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。所以 SqlSessionFactory 的最佳做用域是应用做用域。 有不少方法能够作到,最简单的就是使用单例模式或者静态单例模式。安全

SqlSession

  每一个线程都应该有它本身的 SqlSession 实例。SqlSession 的实例不是线程安全的,所以是不能被共享的,因此它的最佳的做用域是请求或方法做用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也毫不能将 SqlSession 实例的引用放在任何类型的托管做用域中,好比 Servlet 框架中的 HttpSession。 若是你如今正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象类似的做用域中。 换句话说,每次收到的 HTTP 请求,就能够打开一个 SqlSession,返回一个响应,就关闭它。 这个关闭操做是很重要的,你应该把这个关闭操做放到 finally 块中以确保每次都能执行关闭。 下面的示例就是一个确保 SqlSession 关闭的标准模式:服务器

SqlSession session = sqlSessionFactory.openSession();
try {
  // 你的应用逻辑代码
} finally {
  session.close();
}

  在你的全部的代码中一致地使用这种模式来保证全部数据库资源都能被正确地关闭。网络

映射器实例(Mapper)

  映射器是一些由你建立的、绑定你映射的语句的接口。映射器接口的实例是从 SqlSession 中得到的。所以从技术层面讲,任何映射器实例的最大做用域是和请求它们的 SqlSession 相同的。尽管如此,映射器实例的最佳做用域是方法做用域。 也就是说,映射器实例应该在调用它们的方法中被请求,用过以后便可丢弃。 并不须要显式地关闭映射器实例,尽管在整个请求做用域保持映射器实例也不会有什么问题,可是你很快会发现,像 SqlSession 同样,在这个做用域上管理太多的资源的话会难于控制。 为了不这种复杂性,最好把映射器放在方法做用域内。下面的示例就展现了这个实践:

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // 你的应用逻辑代码
} finally {
  session.close();
}

    这个就是咱们在编程式的使用里面看到的四个对象的生命周期的总结。

核心配置解读

  第一个是config 文件。大部分时候咱们只须要不多的配置就可让MyBatis 运行起来。其实MyBatis 里面提供的配置项很是多,咱们没有配置的时候使用的是系统的默认值。

  目前最新的版本是3.5.1,你们能够从官方上下载到最新的源码。中文地址:http://www.mybatis.org/mybatis-3/zh/index.html

<?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="db.properties"></properties>
    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
        <!-- 控制全局缓存(二级缓存)-->
        <setting name="cacheEnabled" value="true"/>
        <!-- 延迟加载的全局开关。当开启时,全部关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的全部属性。默认 false,可经过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--  Mybatis 建立具备延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--
                <setting name="localCacheScope" value="STATEMENT"/>
        -->
        <setting name="localCacheScope" value="SESSION"/>
    </settings>

    <typeAliases>
        <typeAlias alias="blog" type="com.wuzz.domain.Blog" />
    </typeAliases>

<!--    <typeHandlers>
        <typeHandler handler="com.wuzz.type.MyTypeHandler"></typeHandler>
    </typeHandlers>-->

    <!-- 对象工厂 -->
<!--    <objectFactory type="com.wuzz.objectfactory.GPObjectFactory">
        <property name="wuzz" value="666"/>
    </objectFactory>-->

<!--    <plugins>
        <plugin interceptor="com.wuzz.interceptor.SQLInterceptor">
            <property name="wuzz" value="betterme" />
        </plugin>
        <plugin interceptor="com.wuzz.interceptor.MyPageInterceptor">
        </plugin>
    </plugins>-->

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="BlogMapper.xml"/>
        <mapper resource="BlogMapperExt.xml"/>
    </mappers>

</configuration>

configuration

  configuration 是整个配置文件的根标签,实际上也对应着MyBatis 里面最重要的配置类Configuration。它贯穿MyBatis 执行流程的每个环节。这里面有不少的属性,跟其余的子标签也能对应上。

  注意:MyBatis 全局配置文件顺序是固定的,不然启动的时候会报错。

properties

  第一个是properties 标签,用来配置参数信息,好比最多见的数据库链接信息。为了不直接把参数写死在xml 配置文件中,咱们能够把这些参数单独放在properties 文件中,用properties 标签引入进来,而后在xml 配置文件中用${}引用就能够了。能够用resource 引用应用里面的相对路径,也能够用url 指定本地服务器或者网络的绝对路径。

  咱们为何要把这些配置独立出来?有什么好处?或者说,公司的项目在打包的时候,有没有把properties 文件打包进去?

  1. 提取,利于多处引用,维护简单;
  2. 把配置文件放在外部,避免修改后从新编译打包,只须要重启应用;
  3. 程序和配置分离,提高数据的安全性,好比生产环境的密码只有运维人员掌握。

settings  

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

设置名 描述 有效值 默认值
cacheEnabled 全局地开启或关闭配置文件中的全部映射器已经配置的任何缓存。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,全部关联对象都会延迟加载。 特定关联关系中可经过设置 fetchType属性来覆盖该项的开关状态。 true | false false
aggressiveLazyLoading 当开启时,任何方法的调用都会加载该对象的全部属性。 不然,每一个属性会按需加载(参考 lazyLoadTriggerMethods)。 true | false false (在 3.4.1 及以前的版本默认值为 true)
multipleResultSetsEnabled 是否容许单一语句返回多结果集(须要驱动支持)。 true | false true
useColumnLabel 使用列标签代替列名。不一样的驱动在这方面会有不一样的表现,具体可参考相关驱动文档或经过测试这两种不一样的模式来观察所用驱动的结果。 true | false true
useGeneratedKeys 容许 JDBC 支持自动生成主键,须要驱动支持。 若是设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能支持但仍可正常工做(好比 Derby)。 true | false False
autoMappingBehavior 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(不管是否嵌套)。 NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior 指定发现自动映射目标未知列(或者未知属性类型)的行为。
  • NONE: 不作任何反应
  • WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'的日志等级必须设置为 WARN)
  • FAILING: 映射失败 (抛出 SqlSessionException)
NONE, WARNING, FAILING NONE
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定驱动等待数据库响应的秒数。 任意正整数 未设置 (null)
defaultFetchSize 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只能够在查询设置中被覆盖。 任意正整数 未设置 (null)
safeRowBoundsEnabled 容许在嵌套语句中使用分页(RowBounds)。若是容许使用则设置为 false。 true | false False
safeResultHandlerEnabled 容许在嵌套语句中使用分页(ResultHandler)。若是容许使用则设置为 false。 true | false True
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的相似映射。 true | false False
localCacheScope MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种状况下会缓存一个会话中执行的全部查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不一样调用将不会共享数据。 SESSION | STATEMENT SESSION
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 | false false
returnInstanceForEmptyRow 当返回行的全部列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (如集合或关联)。(新增于 3.4.2) true | false false
logPrefix 指定 MyBatis 增长到日志名称的前缀。 任何字符串 未设置
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置
proxyFactory 指定 Mybatis 建立具备延迟加载能力的对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 以上)
vfsImpl 指定 VFS 的实现 自定义 VFS 的实现的类全限定名,以逗号分隔。 未设置
useActualParamName 容许使用方法签名中的名称做为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,而且加上 -parameters 选项。(新增于 3.4.1) true | false true
configurationFactory 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) 类型别名或者全类名. 未设置

typeAliases

  TypeAlias 是类型的别名,跟Linux 系统里面的alias 同样,主要用来简化全路径类名的拼写。好比咱们的参数类型和返回值类型均可能会用到咱们的Bean,若是每一个地方都配置全路径的话,那么内容就比较多,还可能会写错。咱们能够为本身的Bean 建立别名,既能够指定单个类,也能够指定一个package,自动转换。配置了别名之后,只须要写别名就能够了,好比com.gupaoedu.domain.Blog都只要写blog 就能够了。MyBatis 里面有系统预先定义好的类型别名,在TypeAliasRegistry 中。

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>

  当这样配置时,Blog 能够用在任何使用 domain.blog.Blog 的地方。也能够指定一个包名,MyBatis 会在包名下面搜索须要的 Java Bean,好比:

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

  每个在包 domain.blog 中的 Java Bean,在没有注解的状况下,会使用 Bean 的首字母小写的非限定类名来做为它的别名。 好比 domain.blog.Author 的别名为 author;如有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}

 

typeHandlers *

  因为Java 类型和数据库的JDBC 类型不是一一对应的(好比String 与varchar),因此咱们把Java 对象转换为数据库的值,和把数据库的值转换成Java 对象,须要通过必定的转换,这两个方向的转换就要用到TypeHandler。有的同窗可能会有疑问,我没有作任何的配置,为何实体类对象里面的一个String属性,能够保存成数据库里面的varchar 字段,或者保存成char 字段?这是由于MyBatis 已经内置了不少TypeHandler(在type 包下),它们所有所有注册在TypeHandlerRegistry 中,他们都继承了抽象类BaseTypeHandler,泛型就是要处理的Java 数据类型。

  当咱们作数据类型转换的时候,就会自动调用对应的TypeHandler 的方法。若是咱们须要自定义一些类型转换规则,或者要在处理类型的时候作一些特殊的动做,就能够编写本身的TypeHandler,跟系统自定义的TypeHandler 同样,继承抽象类BaseTypeHandler<T>。有4 个抽象方法必须实现,咱们把它分红两类:set 方法从Java 类型转换成JDBC 类型的,get 方法是从JDBC 类型转换成Java 类型的。

  好比咱们想要在获取或者设置String 类型的时候作一些特殊处理,咱们能够写一个String 类型的TypeHandler

public class MyTypeHandler extends BaseTypeHandler<String> {
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
            throws SQLException {
        // 设置 String 类型的参数的时候调用,Java类型到JDBC类型
        // 注意只有在字段上添加typeHandler属性才会生效
        // insertBlog name字段
        System.out.println("---------------setNonNullParameter1:"+parameter);
        ps.setString(i, parameter);
    }

    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 根据列名获取 String 类型的参数的时候调用,JDBC类型到java类型
        // 注意只有在字段上添加typeHandler属性才会生效
        System.out.println("---------------getNullableResult1:"+columnName);
        return rs.getString(columnName);
    }

    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 根据下标获取 String 类型的参数的时候调用
        System.out.println("---------------getNullableResult2:"+columnIndex);
        return rs.getString(columnIndex);
    }

    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        System.out.println("---------------getNullableResult3:");
        return cs.getString(columnIndex);
    }
}

  第二步,在mybatis-config.xml 文件中注册:

<typeHandlers>
<typeHandler handler="com.wuzz.type.MyTypeHandler"></typeHandler>
</typeHandlers>

  第三步,在咱们须要使用的字段上指定,好比:插入值的时候,从Java 类型到JDBC 类型,在字段属性中指定typehandler:

<insert id="insertBlog" parameterType="com.wuzz.domain.Blog">
  insert into blog (bid, name, author_id)
  values (#{bid,jdbcType=INTEGER},
  #{name,jdbcType=VARCHAR,typeHandler=com.wuzz.type.MyTypeHandler},
  #{authorId,jdbcType=INTEGER})
</insert>

  返回值的时候,从JDBC 类型到Java 类型,在resultMap 的列上指定typehandler:

<result column="name" property="name" jdbcType="VARCHAR"
typeHandler="com.wuzz.type.MyTypeHandler"/>

处理枚举类型

  若想映射枚举类型 Enum,则须要从 EnumTypeHandler 或者 EnumOrdinalTypeHandler 中选一个来使用。

  好比说咱们想存储取近似值时用到的舍入模式。默认状况下,MyBatis 会利用 EnumTypeHandler 来把 Enum 值转换成对应的名字。

  注意 EnumTypeHandler 在某种意义上来讲是比较特别的,其余的处理器只针对某个特定的类,而它不一样,它会处理任意继承了 Enum 的类。

  不过,咱们可能不想存储名字,相反咱们的 DBA 会坚持使用整形值代码。那也同样垂手可得: 在配置文件中把 EnumOrdinalTypeHandler 加到 typeHandlers 中便可, 这样每一个 RoundingMode 将经过他们的序数值来映射成对应的整形数值。

objectFactory *

  当咱们把数据库返回的结果集转换为实体类的时候,须要建立对象的实例,因为咱们不知道须要处理的类型是什么,有哪些属性,因此不能用new 的方式去建立。在MyBatis 里面,它提供了一个工厂类的接口,叫作ObjectFactory,专门用来建立对象的实例,里面定义了4 个方法。

public interface ObjectFactory {
    void setProperties(Properties var1);

    <T> T create(Class<T> var1);

    <T> T create(Class<T> var1, List<Class<?>> var2, List<Object> var3);

    <T> boolean isCollection(Class<T> var1);
}

  ObjectFactory 有一个默认的实现类DefaultObjectFactory,建立对象的方法最终都调用了instantiateClass(),是经过反射来实现的。若是想要修改对象工厂在初始化实体类的时候的行为,就能够经过建立本身的对象工厂,继承DefaultObjectFactory 来实现(不须要再实现ObjectFactory 接口)。

public class MyObjectFactory extends DefaultObjectFactory {
    @Override
    public Object create(Class type) {
        System.out.println("建立对象方法:" + type);
        if (type.equals(Blog.class)) {
            Blog blog = (Blog) super.create(type);
            blog.setName("object factory");
            blog.setBid(1111);
            blog.setAuthorId(2222);
            return blog;
        }
        Object result = super.create(type);
        return result;
    }
}

  咱们能够直接用自定义的工厂类来建立对象:

public class ObjectFactoryTest {
    public static void main(String[] args) {
        MyObjectFactory factory = new MyObjectFactory();
        Blog myBlog = (Blog) factory.create(Blog.class);
        System.out.println(myBlog);
    }
}

应用场景举例:

  好比有一个新锐手机品牌在一个电商平台上面卖货,为了让预定数量好看一点,只要有人预定,预定数量就自动乘以3。这个时候就能够建立一个ObjectFactory,只要是查询销量,就把它的预定数乘以3 返回这个实体类。

一、何时调用了objectFactory.create()?

  建立DefaultResultSetHandler 的时候,和建立对象的时候。

二、建立对象后,已有的属性为何被覆盖了?

  在DefaultResultSetHandler 类的395 行getRowValue()方法里面里面调用了applyPropertyMappings()。

三、返回结果的时候,ObjectFactory 和TypeHandler 哪一个先工做?

  先是ObjectFactory,再是TypeHandler。确定是先建立对象。PS:step out 能够看到一步步调用的层级。

插件(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 是负责执行低层映射语句的内部对象。

environments、environment

  environments 标签用来管理数据库的环境,好比咱们能够有开发环境、测试环境、生产环境的数据库。能够在不一样的环境中使用不一样的数据库地址或者类型。

<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

  一个environment 标签就是一个数据源,表明一个数据库。这里面有两个关键的标签,一个是事务管理器,一个是数据源。

transactionManager

  若是配置的是JDBC,则会使用Connection 对象的commit()、rollback()、close()管理事务。若是配置成MANAGED,会把事务交给容器来管理,好比JBOSS,Weblogic。由于咱们跑的是本地程序,若是配置成MANAGE 不会有任何事务。若是是Spring + MyBatis , 则没有必要配置, 由于咱们会直接在applicationContext.xml 里面配置数据源,覆盖MyBatis 的配置。

mappers

  <mappers>标签配置的是咱们的映射器,也就是Mapper.xml 的路径。这里配置的目的是让MyBatis 在启动的时候去扫描这些映射器,建立映射关系。咱们有四种指定Mapper 文件的方式:

  1. 使用相对于类路径的资源引用(resource)
  2. 使用彻底限定资源定位符(绝对路径)(URL)
  3. 使用映射器接口实现类的彻底限定类名
  4. 将包内的映射器接口实现所有注册为映射器(最经常使用)
<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用彻底限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的彻底限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现所有注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>
相关文章
相关标签/搜索