MyBatis — Java 持久层框架学习笔记

后端2015-09-150 篇评论 Java

现今的 Web 服务器端应用,几乎所有的请求都牵扯到数据库的读写。可以说,对数据库的操作是服务器端应用的核心。特别是一些类信息管理系统,完全是针对数据库中的海量数据处理而开发的。数据库的 CRUD(Create, Retrieve, Update, Delete)便成了如今服务器开发的重中之重,往往成为软件项目开发中最耗费时间也是最多 BUG 的一项任务了。

而 CRUD 的实现往往涉及到大量的 SQL 语句的编写,分别对不同的请求执行不同的 SQL 语句,数据库复杂的话,这便成了一项浩大的工程。除此之外,若只是使用较为原始的 JDBC 进行查询的话,数据库中查询的数据是以结果集类型返回的,还需要进一步地处理转换成 Map、List 或是 JavaBean 类型。而开发完成之后的维护及更新,则更让人抓狂。可以说,在大型项目的开发之中,只是单纯的使用 JDBC 几乎已经成为了不可能的事,必须使用一些持久层框架来完成这项工程。

MyBatis 简介

MyBatis 便是一个半自动化的 Java 持久层框架,基于 ORM(Object Relational Mapping, 关系对象映射)。相比于 Hibernate 等全自动化的持久层框架,它为开发人员带来了较高的自主性,对于每一项查询,MyBatis 的 SQL 语句都需要开发者自己编写,而不是由框架自动产生,由此可带来更为灵活的控制。MyBatis 可以与 Spring 等 MVC 框架轻松地结合,完全简化 DAO(Data Access Object, 数据库访问对象)层的开发。

本文通过 MyBatis 在 Spring 中的实现来说明 MyBatis 的使用。需要 Mybatis 及 MyBatis-Spring 等几个 jar 包,这里不一一列举。

使用 MyBatis

配置文件

下面是 Spring 配置文件中 MyBatis 与 Spring 的连接配置:

<!-- DBCP 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://127.0.0.1/dbname?useUnicode=true&amp;characterEncoding=UTF-8" />
    <property name="username" value="username" />
    <property name="password" value="password"/>
    <property name="maxActive" value="50"></property>
    <property name="maxIdle" value="30"></property>
    <property name="maxWait" value="100"></property>
    <property name="defaultAutoCommit" value="true"></property>
</bean>

<!-- MyBatis 配置 -->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />

    <!-- MyBatis 配置文件 -->
    <property name="configLocation" value="classpath:resources/mybatis-config.xml"/>

    <!-- MyBatis 映射文件路径配置 -->
    <property name="mapperLocations" value="classpath:resources/mappers/*.xml"></property>

    <!-- MyBatis 类型关联包路径配置 -->
    <property name="typeAliasesPackage" value="com.packname.model" />
</bean>

<!-- MyBatis 自动映射类包配置 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.packname.mapper" />
    <property name="sqlSessionFactoryBeanName" value="sessionFactory"></property>
</bean>

与 Spring 相连接后,MyBatis 配置文件需要手动配置的项目已经不多,具体可以自行百度。

DAO 层中的使用

MyBatis 当然是出现在 Spring 的 DAO 层之中,下面来看一个例子。

public interface UserMapper {

    /**
     * 通过用户 id 获取用户对象
     * @param id - 用户 id
     * @return 用户对象
     */
    public User getUserById(int id);

    /**
     * 通过用户 id 删除用户
     * @param id - 用户 id
     * @return 删除的行数
     */
    public int deleteUserById(int id);

    /**
     * 通过用户 id 和状态更新用户状态
     * @param userId - 用户 id
     * @param toState - 需要更新到的状态
     * @return 更新的行数
     */
    public int updateUserState(@Param("userId") int userId, @Param("toState") int toState);
`

可以看出,把 MyBatis 融合进来后,Spring 的 DAO 层已不再是作为一个个 Class(类),Interface(接口)出现了。在 DAO 层中,你只需只写出方法的名字、参数和返回值类型,而不需要写出其实现过程。需要说明的是,MyBatis 对多参数的传递并没有很好的封装,而是需要自己在形参前绑定参数名,否则 MyBatis 将无法识别参数的顺序。这些接口的实现过程,则单独在每个同名的 XML 文件做配置,这些 XML 文件便是 MyBatis 的核心。

下面是 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="com.packname.mapper.UserMapper"> 

    <!-- 开启 MyBatis 默认缓存 -->
    <cache />

    <!-- 结果映射 -->
    <resultMap type="User" id="UserResult"> 
         <id property="id" column="id" /> 
         <result property="username"     column="username"/> 
         <result property="password"     column="password"/> 
         <result property="userType"     column="user_type"/> 
         <result property="telNumber"     column="tel_number"/> 
         <result property="email"         column="email"/> 
         <result property="lastActive"     column="last_active"/> 
         <result property="state"         column="state"/> 
    </resultMap>

    <!-- 继承的结果映射 -->
    <resultMap type="Student" id="StudentResult" extends="UserResult">
        <result property="schoolNumber" column="school_number"/>
        <result property="sportPass"     column="sport_pass"/>
        <result property="libPass"         column="lib_pass"/>
    </resultMap>

    <!-- 带有关系对象映射的结果映射,这是 MyBatis 的一个杀手锏 -->
    <resultMap type="Student" id="StudentDetailResult" extends="StudentResult">
        <!-- 依据 id 直接调用本 Mapper 中的方法进行联合查询 -->
        <association property="subscribeNum"
            javaType="int"
            column="id"
            select="getSubscribeNumByUserId"></association>

        <!-- 调用其它 Mapper 中的方法进行查询 -->
        <association property="commentNum"
            javaType="int"
            column="id"
            select="com.packname.mapper.CommentMapper.getCommentNumByUserId" />

    </resultMap>

    <!-- 查询 -->
    <select id="getUserById"
        resultMap="UserResult">
        SELECT * FROM users
        WHERE id = #{id}
    </select>

    <!-- 使用带有关系对象映射结果集的查询,多表联查只需要查询单表 -->
    <select id="getStudentDetailById"
        resultMap="StudentDetailResult">
        SELECT * FROM plate_users
        WHERE id = #{id} AND user_type = "XS"
    </select>

    <!-- 删除 -->
    <delete id="deleteUserById">
        DELETE FROM users WHERE id = #{id}
    </delete>

    <!-- 带有多项参数的更新 -->
    <update id="toggleUserState">
        UPDATE users
        SET state = #{toState}
        WHERE id = #{userId}
    </update>
</mapper>

MyBatis 的使用感受

首先配置的 resultMap 使得 MyBatis 从数据库中获取的数据可以直接转换为相应的 Java Bean 类型,并且也如同 Java 对象那样可以继承,抛弃 JDBC 手工转换的繁琐。针对每一项 CRUD,MyBatis 仍然需要手工编写 SQL 语句。其动态 SQL 也是其一大特色(本文并未提供实例),通过 where、if、when 等类似于 JSTL 的标签,以层次化的方式来动态拼装 SQL,相比 JDBC 对 SQL 杂乱的拼装,显然类似于模板的设计使得其 SQL 语句的维护容易地多。

Mybatis 中的 SQL 并不需要考虑多表的联系,只需如同 JDBC 单表查询那样,就能有其它 ORM 框架那样依据主键把所有与其有联系的数据给查询出来。当然,由于 MyBatis 的半自动化 ORM,开发者可以依据自身需要以及数据的复杂度来决定从数据库中的数据读取,而不是向 Hibernate 那样一股脑全都拉来而没有半点用处。

由于 ORM 无法对查询的数据进行精确的控制,因此需要较高的数据库性能。而 MyBaits 正考虑了这点,内置缓存模块,可以对所有已查寻到的数据序列化存储在本地,默认情况下,在同一个 Mapper 作用域中,如果没有发生 Update、Insert 或者 Delete 等影响查询结果的 SQL 语句,则当查询相同的数据时,会返回缓存中的结果,以免给数据库服务器带来更大的压力。

MyBatis 的出现,简化了 JDBC 中纷繁复杂的 SQL 语句的编写,且提供了对查询结果的深层次的封装,用于取代最为基本的 JDBC 还是相当有优势的。相比于更加简单粗暴的 Hibernate,显然 MyBatis 更加容易控制。因此,介于两者之间的 MyBatis,将两者的优势结合起来,取其精华,去其糟粕,不失为一个相当棒的 Java 持久层框架。

因为时间仓促,本文仅介绍了少数 MyBatis 的特点及用法,更多关于 MyBatis 的介绍及文档,请访问 MyBatis 官网: http://mybatis.github.io/mybatis-3/

针对本文的错误及疏漏,欢迎读者指出,不胜感激。

评论区

发表评论
用户名
(必填)
电子邮箱
(必填)
个人网站
(选填)
评论内容
Copyright © 2017 dremy.cn
皖ICP备16015002号