既然已经入”坑“mybatis了,你竟然还想着挣脱,我是不会让你挣脱的~

当然我有一个算是挣脱的办法。那就是把它学会、理解透。这样我们也就不用在坑里一直徘徊,也算得上是一种挣脱吧!

我在[上一篇文章](file:///E:/LearnNote/后端/Java/mybatis/mybatis入"坑"第一步.md)中对创建一个mybatis项目过程中有过的简单的解释,这篇文章对增加mybatis生命周期和更加详细的配置的说明和解释以及在配置的可能会遇到的关键问题。

一、mybatis作用域与生命周期

如下图是mybatis简易的生命周期图。首先mybatis通过IO流的方式获取配置文件mybatis.config.xml的信息,然后利用SqlSessionFactoryBuilder创建SqlSessionFactory,而SqlSessionFactory是在一个mybatis中是以单例形式存在的,接着利用SqlSessionFactory生产SqlSession,接着利用SqlSession调用SQL Mapper去处理具体的业务。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder的作用就是用来创建SqlSessionFactory的,所以创建完成SqlSessionFactory后便可以将其丢弃,所以SqlSessionFactoryBuilder的作用域最好就是在局部方法中。当需要它是可以再次重用,但是不要一直保留。

SqlSessionFactory

SqlSessionFactory被创建成功后,你应该保证它在运行期间一直存在,因为每一个业务都需要同样的SqlSessionFactory去创建SqlSession。因此 SqlSessionFactory 的最佳作用域是应用作用域。也就是要使SqlSessionFactory在每一个mybatis中都是以单例形式存在的。

SqlSession

SqlSession 的实例不是线程安全的,是不能被共享的,所以作用域最好是在局部方法中。同时对于每一次请求SqlSession,返回一个响应后,应该及时关闭它。

Mapper映射器实例

Mapper映射器接口的实例是从 SqlSession 中获得的,最好将映射器放在方法作用域内,这样可以更好的管理。Mapper代表的是一个具体的业务处理,所以当处理完该业务时就可以丢弃。Mapper是随着SqlSession的关闭而消失废弃的

二、mybatis关键配置详解

properties属性

properties标签:可以动态配置属性。

可以全部在外部进行配置,如下:

<properties resource="db.properties" />

也可以在通过property标签一部分在外部进行内部配置另一部分在内部进行配置(如下),增加配置的灵活性。

<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>

当外部的db.properties文件进行配置之后,在property标签中又配置一遍后会使用哪一个配置呢?

这就需要考虑优先级的问题,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。这里我们的db.properties文件时通过resource指定的,所以优先级大于properties元素指定的属性。所以优先使用外部的db.properties文件中的配置。

typeAliases类型别名

配置Mapper.xml的类型别名可以降低书写冗余的全限定类名。通过对实体类别名的配置,简化开发人员的书写的代码量。比如需要书写com.wkx.pojo.User的全限定类名,在配置别名后便可以仅仅书写user。

那么如何去配置类型别名呢?

第一种:通过typeAlias的标签去配置,这样需要对每一个实体类进行分别配置。type属性中为实体类的路径,alias属性为别名名称。

<!--配置别名-->
<typeAliases>
<typeAlias type="com.wkx.pojo.User" alias="user"/>
</typeAliases>

第二种:通过package标签属性去配置,name属性为实体类所在的包路径。

在无注解的情况下,使用 Bean 的首字母小写的非限定类名来作为它的别名,比如com.wkx.pojo.User的别名便是user

<!--配置别名-->
<typeAliases>
<package name="com.wkx.pojo"/>
</typeAliases>

在有注解的情况下,使用注释的别名进行配置。

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

使用注解后便可以通过注解的内容进行类型配置

<mapper namespace="com.wkx.dao.UserMapper">
<select id="getUser" resultType="wkx">
select * from user
</select>
</mapper>

下面列出关于Java类型内建的类型别名,这里只列出一部分,其他的类型的别名可以依次类推。比如别名为_double,映射类型为double;别名为double,对应映射类型为Double。

别名 映射的类型
_int int
_integer int
int Integer
integer Integer
map Map
hashMap HashMap

environments环境配置

用于配置数据的环境。可配置多个数据库环境,但是SqlSessionFactory只能选择一个去使用。如下:

<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>
<environment id="test">
<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>

可以在不同的环境下切换不同的数据环境,只需要修改environments标签中的default属性对应不同环境下的id属性,比如development和test不同的环境。

  • 事务管理器(transactionManager)

    在mybatis中有两种不同的事务管理器,即type="JDBC"或者type="MANAGED"

    JDBC的事务类型是直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。

    MANAGED的事务类型配置几乎没有做什么,从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。

  • 数据源(dataSource)

    主要有三种数据源类型,即type="[UNPOOLED|POOLED|JNDI]"。

    UNPOOLED的数据源类型是不使用连接池,每次请求时都会打开和关闭连接,显然这样的连接数据源类型效率不高。

    POOLED的数据源类型是使用连接池的概念,每次请求可以直接从“池”子里拿出活跃的连接,避免了重复的创建连接,提高效率。

    JNDI的数据源类型实现是为了能让在 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

mappers映射器

定义映射的路径,告诉mybatis去哪里找对应的语句。我们可以是使用类路径的资源引用方式(推荐使用):

<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="com/wkx/dao/AuthorMapper.xml"/>
</mappers>

可以通过使用完全限定资源定位符(URL)的方式(方式二):

<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///E:/UserMapper.xml"/>
</mappers>

可以通过映射器接口实现类的完全限定类名的方式(方式三):

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="com.wkx.dao.UserMapper"/>
</mappers>

可以包的形式将映射器接口全部注册为映射器的方式(方式四):

<mappers>
<package name="com.wkx.dao"/>
</mappers>

注意:方式三和方式四使用需要具备两个条件,一个是接口和Mapper的名称一致,比如UserMapper.java接口和UserMapper.xml必须都是UserMapper,也就是一致的。另一个是接口和Mapper的包名一致。

入“坑”mybatis后如何挣脱?的更多相关文章

  1. 入坑wsl

    用了一个月的mac os, 又回归windows了, mac确实好看, 终端配合iterm2也很舒服, 奈何终究我们不合适...生态毕竟没有windows那么丰富; 切回windows最无法忍受的就是 ...

  2. RoboGuice 3.0 (一)入坑篇

    RoboGuice是什么? 一个Android上的依赖注入框架. 依赖注入是什么? 从字面理解,这个框架做了两件事情,第一是去除依赖,第二是注入依赖.简单理解就是,将对象的初始化委托给一个容器控制器, ...

  3. webpack入坑之旅(六)配合vue-router实现SPA

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

  4. webpack入坑之旅(四)扬帆起航

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

  5. webpack入坑之旅(三)webpack.config入门

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

  6. webpack入坑之旅(二)loader入门

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack 在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

  7. webpack入坑之旅(一)不是开始的开始

    最近学习框架,选择了vue,然后接触到了vue中的单文件组件,官方推荐使用 Webpack + vue-loader构建这些单文件 Vue 组件,于是就开始了webpack的入坑之旅.因为原来没有用过 ...

  8. gulp入坑系列(2)——初试JS代码合并与压缩

    在上一篇里成功安装了gulp到项目中,现在来测试一下gulp的合并与压缩功能 gulp入坑系列(1)--安装gulp(传送门):http://www.cnblogs.com/YuuyaRin/p/61 ...

  9. ReactNative for Android入坑(一)

    最近找工作发现有些公司要求会ReactNative,决定入坑. 搭建环境:官网详细的教程附链接. 坑一:FQ,建议整个搭建过程中FQ.(FQ链接,注册有200M试用流量,环境搭建够了)第一步:安装Ch ...

随机推荐

  1. 从执行上下文(ES3,ES5)的角度来理解"闭包"

    目录 介绍执行上下文和执行上下文栈概念 执行上下文 执行上下文栈 伪代码模拟分析以下代码中执行上下文栈的行为 代码模拟实现栈的执行过程 通过ES3提出的老概念-理解执行上下文 1.变量对象和活动对象 ...

  2. GPUImage移植总结

    项目github地址: aoce 我是去年年底才知道有GPUImage这个项目,以前也一直没有在移动平台开发过,但是我在win平台有编写一个类似的项目oeip(不要关注了,所有功能都移植或快移植到ao ...

  3. Java堆的理解

    堆的核心概述 所有的对象实例以及数组都应当在运行时分配在堆上 从实际实用角度看 --"几乎所有的对象实例都在堆中分配内存" 数组和对象可能永远不会存储在栈上,因为栈帧中保存引用,这 ...

  4. JS中函数定义和使用顺序

    在js中如果定义函数是先声明函数,如: console.log(hello); //然后再去定义: function hello(){ alert("Hello");} 这种是可以 ...

  5. mate桌面用户 root 自动登录lightdm.conf -20190520 方法【fedora 21】mate

    桌面用户自动登录lightdm.conf -20190520 方法修改 /etc/lightdm/lightdm.conf 步骤:1 vim  /etc/lightdm/lightdm.conf 解除 ...

  6. 马哥Linux SysAdmin学习笔记(四)

    sed:编辑器 sed:Stream EDitor,行编辑器 用法: sed [option]... 'script' inputfile... script: '地址命令' 常用选项: -n:不输出 ...

  7. Linux进阶之Linux中的标准输入输出

    Linux中的标准输入输出 标准输入0    从键盘获得输入 /proc/self/fd/0 标准输出1    输出到屏幕(即控制台) /proc/self/fd/1 错误输出2    输出到屏幕(即 ...

  8. CAP 与数据一致性

    分布式系统的假设是,工作在网络环境下的系统拥有多个节点,而这些节点本身会由于各种原因而变得不稳定.这其中就有一个非常重要的概念--CAP原理.这个原理指导着大多数分布式系统的设计过程,CAP原理大致是 ...

  9. wait 和waitpid函数对比-(转自 wintree)

    Wait和waipid函数 当一个进程正常或异常终止的时候,内核就像其父进程发送SIGCHLD信号,因为子进程是个一步事件,所以这种信号也是内核系那个父进程发的异步通知.父进程可以选择忽略该信号,或者 ...

  10. fprintf函数

    描述 C 库函数 int fprintf(FILE *stream, const char *format, ...) 发送格式化输出到流 stream 中. 声明 下面是 fprintf() 函数的 ...