一、Mybatis框架简单介绍和环境构建

  众所周知,在开发大多数系统的后台时,都能粗略地把任务分为表现交互层业务服务层数据持久层,Mybatis就是这样一个位于数据持久层的框架。经过一天的资料查阅,我准备将对它的认识记录在该博客中。

Mybatis框架的作用有:

  1. 能管理数据库连接池,配置完成后就无需再关心数据库连接即可直接和数据库进行会话。
  2. 拥有 灵活的 ORM功能,可以自定义ORM过程中大多数中间类。(比如类型映射,对象工厂等)
  3. 通过配置mapper文件可以手写 动态的 sql语句将结果集映射到对象中。
  4. 通过第二点,能很方便的写一个DAO类。
  5. 支持存储过程和事务。具有一级、二级缓存功能。
  6. 能很方便的和Spring等框架进行集成。

  Mybatis就是这样的一个框架。在它的官网,能获取到一些较为简单的介绍:http://www.mybatis.org/spring/zh/index.html

由于我是通过Maven项目使用的该框架,所以使用之前需要编写pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.data</groupId>
    <artifactId>datatest1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.20.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <!-- 依赖关系 -->
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!-- junit.jar -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
    </dependencies>

</project>

pom.xml文件中,最主要的依赖便是数据库驱动和mybatis了。定义好pom后,再编写mybatis本身所需要的配置文件,就可以快速开始了。

二、Mybatis的主要基础组件及生命周期

  在写MyBatis的配置文件之前,我先理一理MyBatis中有哪些重要的组件,他们的生命周期是什么样的,以及为什么需要这个配置文件。相信看了下面,心中应该会有较为明确的答案。

MyBatis最重要的基础组件有:
SqlSessionFactoryBuilder: 结构化查询语言会话工厂构造器,该构造器将会读入Mybatis的xml配置文件或者设置好的Configuration对象来获得一个结构化查询语言会话工厂(SqlSessionFactory)。所以,通常在获取到工厂后它就没有其它作用了,也就是可以被销毁了。

SqlSessionFactory: 结构化查询语言会话工厂,该工厂用于获取结构化查询语言会话(SqlSession),也可以获取之前构造该工厂时的配置对象。由于该对象管理着数据库连接池,所以在一般情况下,对于同一个数据库实例,我们应该只创建一个静态最终的该对象。

SqlSession: 结构化查询语言会话,该对象用于和数据库的交互,即可以发送SQL也并返回结果,也可以获取映射接口的对象。相当于JDBC中的Connection对象。通过获取映射接口的对象可以通过方法调用来实现SQL的发送和返回。由于它只存在于数据库事务过程中,所以在事务执行完成后不需要使用它时,需要通过finally语句及时地保证正确地关闭它,否则将造成资源泄漏。

Mapper: 映射器,它是由一个Java接口和XML文件构成的对象(也可以由接口和注解组成),需要给出对应的SQL和映射规则,由SqlSession.getMapper(xxx.class)来得到它。它也可以负责发送SQL去执行并返回结果。和SqlSession是同级别的东西,只是用起来更加简单,可读。所以,它应该和它的会话保持同样的生命周期。以保证程序的正确运行与健壮。

三、MyBatis的环境配置以及映射配置

  在环境配置文件中,我们可以设置数据库连接池的配置,事务管理器的配置,还必须配置数据库驱动,连接地址以及账号和密码。以上这些东西组成一个 “环境” ,而MyBatis的环境配置文件可以配置多个环境。以方便在代码中获取该环境的会话工厂。如果需要使用该框架,最后还需要将映射配置到mappers标签中。
比较全面的环境配置示例和注释如下:
myBatisConfig.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>
<!-- 通过该标签可以为配置增加属性,以便配置文件的上下文中以"${name}"的形式引用它
     也可以通过properties的 resource 属性引用属性文件
	<properties [resource="xxxx.properties"]>
		<property name="driver" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://xxxxxxx />
		....
	</properties>
-->
<!--设置可以配置MyBatis的缓存,延迟加载,映射相关,日志打印等等等高级配置.
<settings>
<setting name="xxxxx" value="xxxx">
.....
</settings>
-->
<!-- 通过该标签可以为类型给一个别名,或者引用一个包名中所有有注解的别名类型 ,以便MyBatis上下文中的引用
	 MyBatis为Java的所有基本类型以及包装类型和部分容器,日期,大数定义好了别名。源码在TypeAliasRegistry类中
	 一般用在映射文件中
	<typeAliases>
		<typeAlias alias = "别名" type="类型" />
		<package name="包名"/>
	</typeAliases>
-->
<!--用于将JDBC类型(jdbcType)和Java类型(javaType)相互转换,MyBatis内置了大部分类型,源码在:TypeHandlerRegistry类中
	可以通过实现typeHandler接口,或者继承BaseTypeHandler类自定义自己的类型处理器
<typeHandlers>
	<typeHandler jdbcType="VARCHAR" javaType="String" handler="com.xxx.xx.xxxHandler">
	.....
</typeHandlers>
-->
<!--MyBatis在构建一个结果集返回时,都会使用对象工厂去构建POJO.默认的对象工厂在 DefaultObjectFactory 类中
可以在这类定制自己的对象工厂,前提是实现ObjectFacotry接口
<objectFactory type="com.xxxx.xxx.MyObjectFactory">
	<property name="name" value="MyObjectFactory" />
</objectFactory>
-->
<!--插件可以改变一些MyBatis的核心行为,比如可以拦截部分数据
<plugins>
</plugins>
-->
    <!-- 注册默认环境配置为development -->
    <environments default="development">
    <!--一个id为 development 的数据库配置环境 , 不同的SqlSessionFactory可以选择不同的环境-->
        <environment id="development">
        	<!-- 采用JDBC事务管理  type="[JDBC|MANAGED|自定义]"-->
            <transactionManager type="JDBC"/>
            <!--指定数据库连接池的属性  type="[UNPOOLED|POOLED|JNDI|自定义]"-->
            <dataSource type="POOLED"> 
                <!-- 1.加载数据库驱动:-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!-- 2.数据库连接地址: -->
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/javatest?
                characterEncoding=utf8&amp;serverTimezone=GMT&amp;useSSL=FALSE"/>
                <!-- 数据库用户... -->
                <property name="username" value="xxxxxxxxxxxxx"/>
                <!-- 数据库密码... -->
                <property name="password" value="xxxxxxxxxxxxxx"/>
            </dataSource>
        </environment>
    </environments>
    <!--数据库厂商标识,若MyBatis有多个不同厂商的数据库管理系统环境,则可以在这为数据库提供一个标识
    	以下是默认的配置,不用自己编写
	<databaseIdProvider type="DB_VENDOR">
		<property name="SQL Server" value="sqlserver" />
		<property name="MySQL Server" value="mysql" />
		<property name="DB2 Server" value="db2" />
		<property name="Oracle Server" value="oracle" />
	</databaseIdProvider>
	-->
    <!-- 注册映射器 -->
    <mappers>
    	<!-- 通过相对路径引用-->
        <mapper resource="com/xxx/xxxxxxx/UserMapper.xml"></mapper>
        <!-- 通过绝对路径引用-->
        <mapper resource="file:var/mappers/com/xxxxx/xxxxx/UserMapper.xml"></mapper>
        <!-- 通过类注册引用 这里需要注意的是,.xml映射文件和接口必须位于同一目录,且文件名相同-->
        <mapper class="com.xxxx.xxxxxx.UserMapper"></mapper>
        <!-- 通过包名引入映射器 条件和上面一样-->
        <package name="com.xxx.xxxxx.xxxx" />
    </mappers>
</configuration>

需要注意的是,因为这里提供了多个设置属性的方法,所以它们是有优先级次序的:
通过方法参数传递的属性 > resource/url属性中指定的配置文件 > properties属性中指定的属性

在之前的文件里注册了一个映射文件,它的作用是定义数据库表和Java对象之间的映射,以及动静态SQL模版,结果集的定义等。由于映射文件的定义比较灵活,一个映射文件也不好演示所有的功能,所以下面的示例文件只演示了一些基本功能:
UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 命名空间和所映射接口的全限定名是一致的 -->
<mapper namespace="org.mapper.UserMapper">
   <!-- 自定义返回结果集 -->
       <resultMap id="userMap" type="org.data.User">
            <id property="id" column="id" javaType="java.lang.Long"></id>
           <result property="name" column="name" javaType="java.lang.String"></result>
           <result property="contact" column="contact" javaType="java.lang.String"></result>
           <result property="telephone" column="telephone" javaType="java.lang.String"></result>
           <result property="email" column="email" javaType="java.lang.String"></result>
           <result property="remark" column="remark" javaType="java.lang.String"></result>
           <result property="photo" column="photo" javaType="java.lang.String"></result>
       </resultMap>
    <!--定义一个插入体,映射为Java接口中的insertUser方法
		通过设置keyProperty和useGeneratedKeys属性可以实现主键回调。
		在该例子中即是将User对象中的id设置为新插入行的主键值。通常用于插入记录后获取其自增id
	 -->
    <insert id="insertUser" keyProperty="id" useGeneratedKeys="true" parameterType="org.data.User">
       insert into customer values(#{name},#{contact},#{telephone},#{email},#{remark},#{photo})
    </insert>
    
    <!--定义一个删除体,映射为Java接口中的deleteUser方法 -->
    <delete id="deleteUser">
        delete from customer where id = #{id}
    </delete>
	
	<!--定义一个修改体,映射为Java接口中的updateUser方法-->
    <update id="updateUser">
        update customer set id = #{user.id},name = #{user.name},contact=#{user.contact}
        ,telephone=#{user.telephone},email=#{user.email},remark=#{user.remark},photo=#{user.photo}
        where id=#{id}
    </update>

	<!--定义一个修改体,映射为Java接口中的updateUser2方法 -->
    <update id="updateUser2">
        update customer set id = #{id},name = #{name},contact=#{contact},telephone=#{telephone}
        ,email=#{email},remark=#{remark},photo=#{photo}
        where id=#{id}
    </update>
    
	 <!--定义一个查询体,映射为Java接口中的selectUserById方法,参数为一个int值,返回类型为org.data.User
	其中 select * from customer where id = #{id} 是SQL模版, #{id} 相当于 JDBC 中的 ? 仅代表一个有可读性的占位符
	将占位符写的和POJO类中的属性名保持一致可以实现自动映射
	-->
    <select id="selectUserById" parameterType="int" resultType="org.data.User">
        select * from customer where id=#{id}
    </select>

	<!--定义一个查询体,映射为Java接口中的selecAllUser方法.返回到上面定义的结果集 userMap 中 -->
    <select id="selectAllUser" resultMap="userMap">
        select * from customer
    </select>
</mapper>

Java映射接口为:
org.mapper.UserMapper

package org.mapper;

import org.apache.ibatis.annotations.Param;
import org.data.User;

import java.util.List;

public interface UserMapper {

    /**
     * 新增用户
     * @param user
     * @return
     * @throws Exception
     */
    public int insertUser(User user)throws Exception;

    /**
     * 修改用户
     * @param user,id
     * @return
     * @throws Exception
     */
    public int updateUser(@Param("user") User user,@Param("id") Long id)throws Exception;

    /**
     * 修改用户2
     * @param user,id
     * @return
     * @throws Exception
     */
    public int updateUser2(User user)throws Exception;

    /**
     * 删除用户
     * @param id
     * @return
     * @throws Exception
     */
    public int deleteUser(Long id)throws Exception;


    /**
     * 根据id查询用户
     * @param id
     * @return
     * @throws Exception
     */
    public int selectUserById(Long id)throws Exception;


    /**
     * 查询所有用户信息
     * @return
     * @throws Exception
     */
    public List<User> selectAllUser()throws Exception;
}

  以上的映射文件及接口则是MyBatis的核心功能了,但由于它的灵活,我没有将动态SQL写到这里,这里只介绍了一些基本的概念及用法。
在映射文件中,最重要的几个概念有:
parameterType:即参数类型,是我们传给Sql语句参数的类型,由于类型处理器的存在,所以SQL参数可以接受Java的基本类型以及引用类型,但需要定义他们之间的映射关系。由于MyBatis已经帮我们注册了Java的通用类型,并且还提供了默认的自动映射功能。所以大多数情况下我们并不需要填写该值。当然,在多参数的情况下是必须填写的。单参数情况下填写也有助于代码的可读性。

resultType:即结果类型,由于插入/更新/删除都是返回的操作成功的条目数,所以结果类型固定为int而不用改动,这里的结果类型参数是用于select标签中的属性,用于定义存储select语句获取的结果集。它也可以是内置的通用类型,也可以是我们定义的POJO,更强大的是还能存储在我们自定义的resultMap中。

resultMap:它是映射集的引用,可以执行强大的映射功能,我们在resultType和resultMap中选择一个作为查询结果的存储集,它能给我们一个自定义映射规则的机会。

  在上面的例子中,演示了很多常用功能,比如主键回填,自定义并使用映射集,单参数和多参数的传参等等等。所以在这里我想介绍一下该映射文件的使用基础:
   在编写以及使用映射文件的过程中,我们要牢记该文件的作用和职能,我们应该为它提供些什么?它又会为我们做哪些工作?只要弄清楚这些,我相信在编写映射时,你不再会为一些莫名其妙的错误感到疑惑。

映射文件 即是用于定义Java和SQL之间关系的文件,它需要一个Java接口用于接受和执行配置文件中的SQL语句,它需要将SQL语句需要的东西以Java的形式传入和返回。这是一个ORM映射文件最基本的东西。在高级功能中它还可以做到根据条件标签动态生成SQL语句,自定义复杂的映射集作为参数或返回集,以及原生SQLMS中有的功能(比如设置超时)和对它的优化(比如结果缓存)等等。

  在这里只谈论最基本的功能,那便是将Java接口和SQL语句联系起来,以及Java类型和SQL类型的映射。

Java与SQL的联系
  在上面的文件中,Java接口和映射xml组合起来表示一组映射关系,MyBatis通过配置文件中的mappers标签可以知道它们的存在。在实际使用中可以通过会话(SessionFactory产生的Session)获取该映射接口,然后通过接口的方法便可以调用SQL语句。

Java类型与SQL类型的映射
单参数映射
  关于Java类型与SQL类型的关系映射,MyBatis主要通过类型注册来实现Java通用类型与SQL类型的映射关系(映射的定义),然后通过自动映射(映射的使用)就可以很方便的实现单参数的传参。自动映射要求表的列名和JavaBean的属性名称相同。如果数据库采用下划线方式命名,JavaBean采用驼峰式命名。则可以通过设置mapUnderscoreToCamelCase = true 来实现自动映射。

多参数映射1
对于多参数传参需要使用map<String,String>的形式并且设该标签属性parameterType=“map”,接口的参数也为对应的map<String,String>来实现。

多参数映射2
或者使用@Param(“xxx”)注解接口参数的形式来手动指定映射,然后再进行传参。

多参数映射3
对于参数比较复杂的情况,以上两种方式可能都不太好。这时我们可以将SQL所需要的参数封装为一个JavaBean,这样一来就将多参数映射转换为了单映射的情况。

结果参数的映射
select语句的返回结果通常都是一个集,所以一般情况下可以用resultType属性来指定容纳这个集的类型,该类型可以是Java基本类型或引用类型。由于是单参数,所以MyBatis会自动帮我们实现自动映射。如果要求更为复杂的映射关系可以像上面那样通过自定义resultMap来实现复杂的映射引用。

Tips:在IDEA中,如果将映射mapper.xml文件放在src目录里,则Mybatis的配置文件会找不到该xml文件。如果是Maven项目可以加上这句话来解决:

    <build>
    <!-- 包含java目录中的xml资源 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
</build>

四、小结

  在本文中,提到了如下几点:

  1. MyBatis环境的构建 – Maven配置
  2. MyBatis中主要基础组件的生命周期
  3. MyBatis的配置文件书写及意义
  4. MyBatis的映射功能的简单描述

五、更加详细的配置文档

更为详细的配置文档:http://www.mybatis.org/mybatis-3/zh/configuration.html#typeAliases


版权声明:本文为qq_32740675原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_32740675/article/details/84998252