一:背景介绍
项目开发中。我们使用的是MyBatis,在MyBatis的xml文件里,两个表的更新功能,写了足足11个更新接口,毫无复用的思想
 
 这种方式可以正常的实现功能,但是没有复用,无论是从时间上还是维护性上,都会增加额外的成本,那么我们该如何解决这个问题呢?如何写出可以复用的语句呢?在下面的例子里我会给大家进行展示
二:前期准备
我们需要准备一个使用MyBatis的maven项目。大家需要提前准备好Mysql数据库
引入pom依赖
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
这里我们只需要引入mysql,mybatis,junit测试三个依赖即可。
 引入之后我们要配置一些数据库的连接问题
数据库连接文件

这里注意将自己数据库机器的ip地址和对应的库名写对,不然无法连接自己的数据库。
MyBatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration mybatis的核心配置文件-->
<configuration>
<!--引入外部配置文件-->
    <properties resource="db.properties"/>
    
    <!--配置-->
    <settings>
        <!--标准日志工厂设置-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
<!--显示的开启全局缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
    
<!--可以给实体类取别名-->
    <typeAliases>
        <!--可以指定一个包名,MyBatis会在包名下面搜索需要的Java Bean-->
        <package name="org.example.pojo"/>
    </typeAliases>
    <!--environments 后面的s表示这是一个复数,可以编写多套环境  default表示默认的环境为development-->
    <environments default="development">
        <!--编写一套环境 名称为configuration-->
        <environment id="development">
            <!--jdbc的事务管理-->
            <transactionManager type="JDBC"/>
            <!--配置数据库相关数据-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <!--userSSL是一个按权连接 &是一个转移符 等同于and  CharacterEncoding=utf-8可以保证输入数据库的数据不乱码-->
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
<!--绑定接口-->
    <mappers>
        <mapper class="org.example.dao.UserInfoMapper"/>
    </mappers>
</configuration>
 
MyBatis配置类
public class MybatisUtils {
    private  static SqlSessionFactory sqlSessionFactory;
    //静态代码块:一旦初始化就加载
    static{
        try {
            //使用Mybatis第一步:获取sqlSessionFactory对象
            //获取资源,直接读到mybatis-config.xml
            String resource = "mybatis-config.xml";
            //需要用到输入流(InputStream) 把resource类加载进来
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //通过build把输入流加载进来
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession() {
        //openSession中有自动commit(提交)事务的方法,加上true就能实现
        return sqlSessionFactory.openSession(true);
    }
}
 
到这里,我们的基本环境就准备好了,可以进行代码的编写
三:通用的更新语句
我写了一个通用的更新语句,将这个语句写好之后,我们可以去上文提到的,两张表 11个更新接口其中一个写了9个更新接口的mapper.xml文件,看一看这个通用的mapper能够覆盖到多少个。
通用update语句
    <update id="updateCourseGroupConfiguration" parameterType="org.example.pojo.UserCourseGroupConfigurationPojo">
        update arpro_user_course_group_configuration
        <trim prefix="SET" suffixOverrides=",1">
            <if test="infoId != null">info_id = #{infoId}</if>
            <if test="courseId != null">course_id = #{courseId}</if>
            <if test="classId != null">class_id = #{classId}</if>
            <if test="groupId != null">group_id = #{groupId}</if>
            <if test="type != null">type = #{type}</if>
            <if test="isDelete != null">is_delete = #{isDelete}</if>
            <if test="remark != null">remark = #{remark}</if>
            <if test="isLike != null">is_like = #{isLike}</if>
        </trim>
        where is_delete = 0
        <if test="infoId != null"> and info_id = #{infoId}</if>
        <if test="courseId != null">and course_id = #{courseId}</if>
        <if test="classId != null">and class_id = #{classId}</if>
        <if test="groupId != null">and group_id = #{groupId}</if>
        <if test="isLike != null">and is_like = #{isLike}</if>
        <if test="type != null">and type = #{type}</if>
    </update>
 
可以覆盖的更新接口
    <update id="updateGroupRelationship">
        UPDATE arpro_user_course_group_configuration
        set group_id = #{newGroupId}
        WHERE
            group_id = #{oldGroupId} and
            type = #{type}
    </update>
    
    <update id="updateGroupIsDelete">
        UPDATE arpro_user_course_group_configuration
        SET is_delete=1
        WHERE class_id = #{classId}
          AND course_id = #{courseId}
    </update>
    <update id="updateGroupIsDeleteByCourseId">
        UPDATE arpro_user_course_group_configuration
        SET is_delete=1
        WHERE  course_id = #{courseId}
    </update>
    <update id="updateGroupRelationshipByClassIdAndCourseId">
        UPDATE arpro_user_course_group_configuration
        set group_id = #{groupCourseModel.newGroupId} ,is_like = #{isLike}
        WHERE
            type = #{groupCourseModel.type} and class_id = #{groupCourseModel.classId} and course_id = #{groupCourseModel.courseId} and info_id =#{groupCourseModel.infoId}
    </update>
    
        <update id="updateCourseIsLike" parameterType="com.tfjy.arprobackend.model.GroupCourseModel">
        UPDATE arpro_user_course_group_configuration
        set  is_like = #{isLike}
        where group_id = #{groupId} and type = #{type}
    </update>
    <update id="updateUserCourseIsLike">
        UPDATE arpro_user_course_group_configuration
        set  is_like = 1
        where info_id = #{infoId} and type = #{type} and group_id != #{groupId}  and is_delete = 0
    </update>
    
    <update id="updateUserCourseNotLike">
        UPDATE arpro_user_course_group_configuration
        set  is_like = 0
        where info_id = #{infoId} and type = #{type} and group_id = #{groupId}  and is_delete = 0
    </update>
    <update id="updateGroupRelation">
        UPDATE arpro_user_course_group_configuration
        set group_id = #{newGroupId} ,info_id = #{newInfoId}
        WHERE
            type = 1 and class_id = #{classId} and course_id = #{courseId} and info_id = #{oldInfoId}
    </update>
 
暂时无法覆盖到的更新接口
    <update id="updateGroupIsDeleteByUserId">
        update `arpro_user_course_group_configuration` set is_delete =1 WHERE course_id=#{courseAndStudentInfoModel.courseId} AND class_id=#{courseAndStudentInfoModel.classId} AND
        info_id IN
        <foreach item="student" collection="studentList" open="(" separator="," close=")">
            #{student}
        </foreach>
    </update>
 
从结果上来看,二者的对比是惊人的。一个通用的更新接口,竟然覆盖了我写的更新的9个接口中的8个,也就是说,在之前的开发中,造了7个重复的轮子。并且至少多了7处使用这些sql语句的地方,多了7个需要维护的代码。
 复用思想多么的重要啊,没有这种思想,写一些重复的代码,不但效率低,时间长,还加大了出错的可能。
四:总结
写代码的时候,一定,一定,一定,要考虑维护的问题,考虑复用的问题。这样我们写出的代码才能不仅可以实现功能,而且还容易维护。
 接下来还要总结MyBatis的动态sql的写法,写出复用性高的sql

















![[ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限](https://img-blog.csdnimg.cn/5aef87cb78a94c29a10e8633cbd8aae5.png)

