Mybatis映射文件SQL-增删查改/批量增删查改/SqlSessionBatch-SqlSessionTemplateBatch/动态拼装SQL/多表连接操作属性使用-模板

增删查改/批量增删查改

<?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.xch.mapper.WorkMapper">

    <resultMap id="BaseResultMap" type="com.xch.pojo.Work">
        <id property="wId" jdbcType="VARCHAR" column="w_id"/>
        <result property="wDept" jdbcType="VARCHAR" column="w_dept"/>
        <result property="wPosition" jdbcType="VARCHAR" column="w_position"/>
        <result property="wSalary" jdbcType="DECIMAL" column="w_salary"/>
        <result property="wCreateTime" jdbcType="TIMESTAMP" column="w_create_time"/>
        <result property="uId" jdbcType="VARCHAR" column="u_id"/>
    </resultMap>

    <sql id="Base_Column_List">
        w_id, w_dept, w_position, w_salary, w_create_time, u_id
    </sql>

    <sql id="Alias_Column_List">
        work.w_id, work.w_dept, work.w_position, work.w_salary, work.w_create_time, work.u_id
    </sql>


    <!--单表增删查改模板-->
    <insert id="baseInsertWork" parameterType="com.xch.pojo.Work">
        insert into dynamic_sql_work
        values (
            #{wId,jdbcType=VARCHAR},
            #{wDept,jdbcType=VARCHAR},
            #{wPosition,jdbcType=VARCHAR},
            #{wSalary,jdbcType=DECIMAL},
            #{wCreateTime,jdbcType=TIMESTAMP},
            #{uId,jdbcType=VARCHAR}
        )
    </insert>

    <delete id="baseDeleteWork" parameterType="string">
        delete from dynamic_sql_work
        where w_id=#{wId,jdbcType=VARCHAR}
    </delete>

    <select id="baseSelectWork" parameterType="string" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_work
        where u_id=#{uId,jdbcType=VARCHAR}
    </select>

    <update id="baseUpdateWork" parameterType="com.xch.pojo.Work">
        update dynamic_sql_work
        set w_position=#{wPosition,jdbcType=VARCHAR},
            w_salary=#{wSalary,jdbcType=DECIMAL},
            w_create_time=#{wCreateTime,jdbcType=TIMESTAMP}
        where u_id=#{uId,jdbcType=VARCHAR}
        and w_id=#{wId,jdbcType=VARCHAR}
    </update>


    <!--单表批量增删查改模板-->
    <insert id="batchInsertWork" parameterType="list">
        insert into dynamic_sql_work
        values
        <foreach collection="workList" item="work" separator=",">
            (
                #{work.wId,jdbcType=VARCHAR},
                #{work.wDept,jdbcType=VARCHAR},
                #{work.wPosition,jdbcType=VARCHAR},
                #{work.wSalary,jdbcType=DECIMAL},
                #{work.wCreateTime,jdbcType=TIMESTAMP},
                #{work.uId,jdbcType=VARCHAR}
            )
        </foreach>
    </insert>

    <delete id="batchDeleteWork" parameterType="list">
        delete from dynamic_sql_work
        where w_id in 
        <foreach collection="wIdList" item="wId" open="(" close=")" separator=",">
            #{wId,jdbcType=VARCHAR}
        </foreach>
    </delete>

    <select id="batchSelectWork" parameterType="list" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_work
        where w_id in 
        <foreach collection="wIdList" item="wId" open="(" close=")" separator=",">
            #{wId,jdbcType=VARCHAR}
        </foreach>
    </select>

    <update id="batchUpdateWork1">
        update dynamic_sql_work
        set w_position=#{work.wPosition,jdbcType=VARCHAR},
            w_salary=#{work.wSalary,jdbcType=DECIMAL},
            w_create_time=#{work.wCreateTime,jdbcType=TIMESTAMP},
            u_id=#{work.uId,jdbcType=VARCHAR}
        where w_id in 
        <foreach collection="wIdList" item="wId" open="(" close=")" separator=",">
            #{wId,jdbcType=VARCHAR}
        </foreach>
    </update>
    
    <update id="batchUpdateWork2" parameterType="list">
        update dynamic_sql_work
        set  w_salary=
        case
        <foreach collection="workList" item="work">
            when w_id=#{work.wId,jdbcType=VARCHAR} then #{work.wSalary,jdbcType=DECIMAL}
        </foreach>
        end
        where w_id in
        <foreach collection="workList" item="work" open="(" close=")" separator=",">
            #{work.wId,jdbcType=VARCHAR}
        </foreach>
    </update>

</mapper>

SqlSessionBatch-SqlSessionTemplateBatch

package com.xch.sqlSessionTemplate;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Chenghe Xu
 * @date 2022/9/5 22:58
 * 
 * 申明多个注入Bean注释,只会注入一个Bean
 * 因为注释的底层都会有@ConditionalOnMissingBean(xxx.class),没有该Bean才创建,防止重复创建
 */
@Configuration
public class CreateSqlSessionTemplate {

    /**
     * 注入开启Batch模式的SqlSessionTemplate对象
     */
    @Bean({"sqlSessionTemplateBatch"})
    @ConditionalOnMissingBean(name = {"sqlSessionTemplateBatch"})
    @Autowired
    public SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
    }

}
package com.xch.dao.impl;

import com.xch.dao.WorkDAO;
import com.xch.mapper.WorkMapper;
import com.xch.pojo.Work;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

/**
 * @author Chenghe Xu
 * @date 2022/9/5 20:47
 */
@Repository
public class WorkDAOImpl implements WorkDAO {
    
    @Resource
    ApplicationContext applicationContext;

    private final SqlSessionFactory sqlSessionFactory;
    private final SqlSessionTemplate sqlSessionTemplate;
    
    /**
     * SqlSessionFactory/SqlSessionTemplate默认在Spring容器中的
     * 注入开启Batch模式的SqlSessionTemplate自定义对象splSessionTemplateBatch
     *      代替原有的SqlSessionTemplate对象
     */
    @Autowired
    public WorkDAOImpl(SqlSessionFactory sqlSessionFactory, @Qualifier("sqlSessionTemplateBatch") SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSessionFactory = sqlSessionFactory;
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    public void test(){
        System.out.println(sqlSessionFactory);
        System.out.println(sqlSessionTemplate);
        System.out.println(applicationContext.getBeansOfType(SqlSessionTemplate.class));
        System.out.println(Arrays.toString(applicationContext.getBeanNamesForType(SqlSessionTemplate.class)));
    }
    
    /**
     * SqlSession/SqlSessionTemplate异同:
     * 1、SqlSession需要手动commit和close流
     *    SqlSessionTemplate自动commit和close流
     * 2、SqlSession并发下线程不安全
     *    SqlSessionTemplate并发下线程安全
     * 3、SqlSessionTemplate是SqlSession的实现类
     *    其底层都是通过jdbc的PreparedStatement.executeBatch()执行批量操作的
     *    
     * 用法:
     * 业务逻辑中其它操作(删查改)混合,使用SqlSession
     * 业务逻辑中只有批量新增操作,使用SqlSessionTemplate
     */
    @Override
    public Integer advanceBatchWork1(List<Work> workList) {
        //try (AutoCloseable/Closeable 需要自动关闭的资源)
        //jdk1.7新特性:try ()中申明的流资源,在try语句结束后自动关闭
        //相当于简化了finally{ManualCloseable 需要手动关闭的资源}
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)){
            WorkMapper workMapper = sqlSession.getMapper(WorkMapper.class);
            workList.forEach(workMapper::baseInsertWork);
            sqlSession.commit();
            return workList.size();
        }
        //不需要捕获catch (){rollback();},发生异常后Spring会回滚方法的执行
    }
    
    @Override
    public Integer advanceBatchWork2(List<Work> workList) {
        //SqlSessionTemplate自动管理了提交commit和关闭流close
        WorkMapper workMapper = sqlSessionTemplate.getMapper(WorkMapper.class);
        workList.forEach(workMapper::baseInsertWork);
        return workList.size();
    }
    
}

动态拼装SQL/多表连接操作属性使用

<?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.xch.mapper.UserMapper">
    
    <resultMap id="BaseResultMap" type="com.xch.pojo.User">
        <id property="uId" jdbcType="VARCHAR" column="u_id"/>
        <result property="uName" jdbcType="VARCHAR" column="u_name"/>
        <result property="uAge" jdbcType="INTEGER" column="u_age"/>
        <result property="uPhone" jdbcType="CHAR" column="u_phone"/>
        <result property="uCreateTime" jdbcType="TIMESTAMP" column="u_create_time"/>
    </resultMap>
    
    <sql id="Base_Column_List">
        u_id, u_name, u_age, u_phone, u_create_time
    </sql>

    <sql id="Alias_Column_List">
        user.u_id, user.u_name, user.u_age, user.u_phone, user.u_create_time
    </sql>


    <!--动态拼装SQL-->
    
    <!--if标签可以判断     not true false null '' ! == != < <= > >=   -->
    <!--if标签可以转义     eq neq lt lte &lt; &lt;= gt gte &gt; %gt;= -->
    <!--if标签可以运算     + - * / % ^ << >> >>> | &                  -->
    <!--if标签可以组合判断 || or && and ? :                           -->
    <!--if标签可以调用方法 xxx.equals() xxx.hashCode()                -->
    <select id="ifTest" parameterType="com.xch.pojo.User" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_user
        where 1=1
        <if test="uName neq null and uName != ''">
            and u_name=#{uName,jdbcType=VARCHAR}
        </if>
        <if test="uAge neq null and uAge >= 0 and uAge lte 160">
            and u_age=#{uAge,jdbcType=INTEGER}
        </if>
    </select>

    <!--where标签可以替代where/where 1=1,动态去除多余and-->
    <select id="whereTest" parameterType="com.xch.pojo.User" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_user
        <where>
            <if test="uName neq null and uName != ''">
                and u_name=#{uName,jdbcType=VARCHAR}
            </if>
            <if test="uAge neq null and uAge >= 0 and uAge lte 160">
                and u_age=#{uAge,jdbcType=INTEGER}
            </if>
        </where>
    </select>

    <!--choose when otherwise标签-->
    <select id="chooseTest" parameterType="com.xch.pojo.User" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_user
        where 1=1
        <choose>
            <when test="uName neq null and uName != ''">
                and u_name=#{uName,jdbcType=VARCHAR}
            </when>
            <when test="uAge neq null and uAge >= 0 and uAge lte 160">
                and u_age=#{uAge,jdbcType=INTEGER}
            </when>
            <otherwise>
                order by u_age, u_id
            </otherwise>
        </choose>
    </select>

    <!--set标签可以代替set,动态去除多余,-->
    <update id="setTest" parameterType="com.xch.pojo.User">
        update dynamic_sql_user
        <set>
            <if test="uName neq null and uName != ''">
                u_name=#{uName,jdbcType=VARCHAR},
            </if>
            <if test="uAge neq null and uAge >= 0 and uAge lte 160">
                and u_age=#{uAge,jdbcType=INTEGER}
            </if>
        </set>
        where u_id=#{uId,jdbcType=VARCHAR}
    </update>

    <!--trim标签可以代替where/where 1=1,动态去除多余and-->
    <select id="trimTest1" parameterType="com.xch.pojo.User" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_user
        <trim prefix="where" prefixOverrides="and">
            <if test="uName neq null and uName != ''">
                and u_name=#{uName,jdbcType=VARCHAR}
            </if>
            <if test="uAge neq null and uAge >= 0 and uAge lte 160">
                and u_age=#{uAge,jdbcType=INTEGER}
            </if>
        </trim>
    </select>
    
    <!--trim标签可以代替set,动态去除多余,-->
    <update id="trimTest2" parameterType="com.xch.pojo.User">
        update dynamic_sql_user
        <trim prefix="set" suffixOverrides=",">
            <if test="uName neq null and uName != ''">
                u_name=#{uName,jdbcType=VARCHAR},
            </if>
            <if test="uAge neq null and uAge >= 0 and uAge lte 160">
                and u_age=#{uAge,jdbcType=INTEGER}
            </if>
        </trim>
        where u_id=#{uId,jdbcType=VARCHAR}
    </update>
    
    
    <!--多表连接操作-->

    <!--association属性-一对一关联-->
    <resultMap id="BaseResultWithWorkMap1" type="com.xch.pojo.UserWithWork">
        <id property="uId" jdbcType="VARCHAR" column="u_id"/>
        <result property="uName" jdbcType="VARCHAR" column="u_name"/>
        <result property="uAge" jdbcType="INTEGER" column="u_age"/>
        <result property="uPhone" jdbcType="CHAR" column="u_phone"/>
        <result property="uCreateTime" jdbcType="TIMESTAMP" column="u_create_time"/>
        <!--说明:property是出参,jdbcType/javaType是指明类型-->
        <association property="work" javaType="com.xch.pojo.Work">
            <id property="wId" jdbcType="VARCHAR" column="w_id"/>
            <result property="wDept" jdbcType="VARCHAR" column="w_dept"/>
            <result property="wPosition" jdbcType="VARCHAR" column="w_position"/>
            <result property="wSalary" jdbcType="DECIMAL" column="w_salary"/>
            <result property="wCreateTime" jdbcType="TIMESTAMP" column="w_create_time"/>
            <result property="uId" jdbcType="VARCHAR" column="u_id"/>
        </association>
    </resultMap>
    <select id="associationTest" parameterType="string" resultMap="BaseResultWithWorkMap1">
        select <include refid="Alias_Column_List"/>,<include refid="com.xch.mapper.WorkMapper.Alias_Column_List"/>
        from dynamic_sql_user user
        left join dynamic_sql_work work
        on user.u_id=work.u_id
        where work.u_id=#{uId,jdbcType=VARCHAR}
    </select>

    <!--collection属性-一对多关联-->
    <resultMap id="BaseResultWithWorkMap2" type="com.xch.pojo.UserWithWork">
        <id property="uId" jdbcType="VARCHAR" column="u_id"/>
        <result property="uName" jdbcType="VARCHAR" column="u_name"/>
        <result property="uAge" jdbcType="INTEGER" column="u_age"/>
        <result property="uPhone" jdbcType="CHAR" column="u_phone"/>
        <result property="uCreateTime" jdbcType="TIMESTAMP" column="u_create_time"/>
        <!--说明:property是出参,jdbcType/ofType是指明类型-->
        <collection property="workList" ofType="com.xch.pojo.Work">
            <id property="wId" jdbcType="VARCHAR" column="w_id"/>
            <result property="wDept" jdbcType="VARCHAR" column="w_dept"/>
            <result property="wPosition" jdbcType="VARCHAR" column="w_position"/>
            <result property="wSalary" jdbcType="DECIMAL" column="w_salary"/>
            <result property="wCreateTime" jdbcType="TIMESTAMP" column="w_create_time"/>
            <result property="uId" jdbcType="VARCHAR" column="u_id"/>
        </collection>
    </resultMap>
    <select id="collectionTest" parameterType="string" resultMap="BaseResultWithWorkMap2">
        select <include refid="Alias_Column_List"/>,<include refid="com.xch.mapper.WorkMapper.Alias_Column_List"/>
        from dynamic_sql_user user
        left join dynamic_sql_work work
        on user.u_id=work.u_id
        where work.u_id=#{uId,jdbcType=VARCHAR}
    </select>

    <!--extend属性-继承映射关系-->
    <resultMap id="BaseResultWithWorkMap3" type="com.xch.pojo.UserWithWork" extends="BaseResultMap">
        <!--说明:property是出参,jdbcType/javaType是指明类型-->
        <association property="work" javaType="com.xch.pojo.Work">
            <id property="wId" jdbcType="VARCHAR" column="w_id"/>
            <result property="wDept" jdbcType="VARCHAR" column="w_dept"/>
            <result property="wPosition" jdbcType="VARCHAR" column="w_position"/>
            <result property="wSalary" jdbcType="DECIMAL" column="w_salary"/>
            <result property="wCreateTime" jdbcType="TIMESTAMP" column="w_create_time"/>
            <result property="uId" jdbcType="VARCHAR" column="u_id"/>
        </association>
    </resultMap>
    <select id="extendTest" parameterType="string" resultMap="BaseResultWithWorkMap3">
        select <include refid="Alias_Column_List"/>,<include refid="com.xch.mapper.WorkMapper.Alias_Column_List"/>
        from dynamic_sql_user user
        left join dynamic_sql_work work
        on user.u_id=work.u_id
        where work.u_id=#{uId,jdbcType=VARCHAR}
    </select>
    
    <!--resultMap属性-继承映射关系-->
    <resultMap id="BaseResultWithWorkMap4" type="com.xch.pojo.UserWithWork" extends="BaseResultMap">
        <!--说明:property是出参-->
        <association property="work" resultMap="com.xch.mapper.WorkMapper.BaseResultMap"/>
    </resultMap>
    <select id="resultMapTest" parameterType="string" resultMap="BaseResultWithWorkMap4">
        select <include refid="Alias_Column_List"/>,<include refid="com.xch.mapper.WorkMapper.Alias_Column_List"/>
        from dynamic_sql_user user
        left join dynamic_sql_work work
        on user.u_id=work.u_id
        where work.u_id=#{uId,jdbcType=VARCHAR}
    </select>
    
    <!--select属性-关联SQL-->
    <resultMap id="BaseResultWithWorkMap5" type="com.xch.pojo.UserWithWork" extends="BaseResultMap">
        <!--说明:property是出参,column是入参:数据库列名/{连接SQL需要的参数名=本SQL提供的数据库列名},逗号分隔-->
        <!--写法一:数据库列名(适用于单一参数)-->
        <!--写法二:{连接SQL需要的参数名=本SQL提供的数据库列名},逗号分隔(适用于多个参数即封装为类,需有GET/SET函数)-->
        <association property="work" column="u_id" select="com.xch.mapper.WorkMapper.baseSelectWork"/>
    </resultMap>
    <select id="selectTest" parameterType="string" resultMap="BaseResultWithWorkMap5">
        select <include refid="Base_Column_List"/>
        from dynamic_sql_user
        where u_id=#{uId,jdbcType=VARCHAR}
    </select>
    
</mapper>

多层结构树综合查询使用比较

<?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.xch.mapper.LevelTreeExtraMapper">

    <resultMap id="BaseResultMap" type="com.xch.pojo.LevelTreeExtra">
        <id property="id" jdbcType="INTEGER" column="id"/>
        <result property="parentId" jdbcType="INTEGER" column="parent_id"/>
        <result property="name" jdbcType="VARCHAR" column="name"/>
        <result property="otherProperties" jdbcType="VARCHAR" column="other_properties"/>
    </resultMap>
    
    <sql id="Base_Column_List">
        id, parent_id, name, other_properties
    </sql>

    <sql id="Alias_Column_List1">
        lt1.id lt1_id, lt1.parent_id lt1_parent_id, lt1.name lt1_name, lt1.other_properties lt1_other_properties
    </sql>

    <sql id="Alias_Column_List2">
        lt2.id lt2_id, lt2.parent_id lt2_parent_id, lt2.name lt2_name, lt2.other_properties lt2_other_properties
    </sql>

    <sql id="Alias_Column_List3">
        lt3.id lt3_id, lt3.parent_id lt3_parent_id, lt3.name lt3_name, lt3.other_properties lt3_other_properties
    </sql>

    <!-- Mysql连接查询语句(不能使用lt1.id形式,需要用别名区分) -->
    <resultMap id="BaseResultWithNextLevelMap" type="com.xch.pojo.LevelTreeExtra">
        <id property="id" jdbcType="INTEGER" column="lt1_id"/>
        <result property="parentId" jdbcType="INTEGER" column="lt1_parent_id"/>
        <result property="name" jdbcType="VARCHAR" column="lt1_name"/>
        <result property="otherProperties" jdbcType="VARCHAR" column="lt1_other_properties"/>
        <collection property="nextLevelTreeList" ofType="com.xch.pojo.LevelTreeExtra">
            <id property="id" jdbcType="INTEGER" column="lt2_id"/>
            <result property="parentId" jdbcType="INTEGER" column="lt2_parent_id"/>
            <result property="name" jdbcType="VARCHAR" column="lt2_name"/>
            <result property="otherProperties" jdbcType="VARCHAR" column="lt2_other_properties"/>
            <collection property="nextLevelTreeList" ofType="com.xch.pojo.LevelTreeExtra">
                <id property="id" jdbcType="INTEGER" column="lt3_id"/>
                <result property="parentId" jdbcType="INTEGER" column="lt3_parent_id"/>
                <result property="name" jdbcType="VARCHAR" column="lt3_name"/>
                <result property="otherProperties" jdbcType="VARCHAR" column="lt3_other_properties"/>
            </collection>
        </collection>
    </resultMap>
    <!-- inner效果为必须有,left效果为可以有,where效果为限定查询开始层级 -->
    <select id="selectLevelTree1" resultMap="BaseResultWithNextLevelMap">
        select <include refid="Alias_Column_List1"/>,
        <include refid="Alias_Column_List2"/>,
        <include refid="Alias_Column_List3"/>
        from level_tree lt1
        inner join level_tree lt2
        on lt1.id = lt2.parent_id
        left join level_tree lt3
        on lt2.id = lt3.parent_id
        where lt1.parent_id = -1
    </select>

    <!-- Mybatis子查询语法(写法一) -->
    <resultMap id="BaseResultWithNextLevelMap1" type="com.xch.pojo.LevelTreeExtra" extends="BaseResultMap">
        <!-- 写法一:数据库列名(适用于单一参数) -->
        <collection property="nextLevelTreeList" column="id" select="selectLevelTree2"/>
    </resultMap>
    <select id="selectLevelTree2" parameterType="com.xch.pojo.LevelTreeExtra" resultMap="BaseResultWithNextLevelMap1">
        select <include refid="Base_Column_List"/>
        from level_tree
        where parent_id = #{parentId}
    </select>
    <!-- Mybatis子查询语法(写法二) -->
    <resultMap id="BaseResultWithNextLevelMap2" type="com.xch.pojo.LevelTreeExtra" extends="BaseResultMap">
        <!-- 写法二:{连接SQL需要的参数名=本SQL提供的数据库列名},逗号分隔(适用于多个参数即封装为类,需有GET/SET函数) -->
        <collection property="nextLevelTreeList" column="{parentId=id}" select="selectLevelTree2"/>
    </resultMap>
    <select id="selectLevelTree22" parameterType="com.xch.pojo.LevelTree" resultMap="BaseResultWithNextLevelMap2">
        select <include refid="Base_Column_List"/>
        from level_tree
        where parent_id = #{parentId}
    </select>
    
    <!-- 业务层手动组装结构树 -->
    <select id="selectLevelTree3" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/>
        from level_tree
        where parent_id is not null
        <!-- 拼装过滤有效数据条件 -->
    </select>
    
</mapper>
/**
 * 组装结构树算法工具方法(可以抽离到公共工具类中定义)
 */
public List<LevelTreeExtra> fixLevelTreeExtra(List<LevelTreeExtra> levelTreeList) {
    // 入参判断(公共的工具方法,需要做强检验,确保健壮性/兼容性/适配性)
    Assert.notEmpty(levelTreeList, "不能组装空集合");
//    if (ObjectUtil.isEmpty(levelTreeList)) {
//        // 返回不可操作的空集合
//        Collections.emptyList();
//    }
    
    // 业务逻辑
    // 先进行JDK8新特性去重再按parentId分组
    Map<Integer, List<LevelTreeExtra>> levelTreeListMapByParentId = levelTreeList.stream()
            .distinct().collect(Collectors.groupingBy(LevelTreeExtra::getParentId));
    // 再递归(DFS)批量组装
    return fixDFS(levelTreeListMapByParentId);
}

/**
 * 递归(DFS)批量组装结果树
 */
public List<LevelTreeExtra> fixDFS(Map<Integer, List<LevelTreeExtra>> levelTreeListMapByParentId) {
    List<LevelTreeExtra> levelTreeExtraList = levelTreeListMapByParentId.get(-1);
    if (ObjectUtil.isEmpty(levelTreeExtraList)) {
        return Collections.emptyList();
    }
    
    levelTreeExtraList.forEach(levelTreeExtra -> DFS(levelTreeListMapByParentId, levelTreeExtra));
    return levelTreeExtraList;
}

/**
 * 递归函数(写法一:参数传递/写法二:调用传递,仅适用于调用者是递归方法体类本身,才可以用this)
 */
public void DFS(Map<Integer, List<LevelTreeExtra>> levelTreeListMapByParentId, LevelTreeExtra levelTreeExtra) {
    // 递归出口(判断的是当前状态的内容,通常判断为结束时,不再做操作)
    List<LevelTreeExtra> nextLevelTreeList = levelTreeListMapByParentId.get(levelTreeExtra.getId());
    if (ObjectUtil.isEmpty(nextLevelTreeList)) {
        return;
    }
    
    // 递归体
    levelTreeExtra.setNextLevelTreeList(nextLevelTreeList);
    nextLevelTreeList.forEach(nextLevelTree -> DFS(levelTreeListMapByParentId, nextLevelTree));
}

其中:

1、基本数据类型可以简写(全小写)代替完整包.类名(可以通过Idea跳转测试)

2、入参有多个时,mybatis接口层用@param("xxx")标注,映射文件SQL不用写入参类型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BB-X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值