入“坑”mybatis后如何挣脱?

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

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

我在上一篇文章(mybatis入“坑”第一步)中对创建一个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的包名一致。