mysql+mybatis递归调用

递归调用的应用场景常常出现在多级嵌套的情况,比如树形的菜单。下面通过一个简单的例子来实现mysql+mybatis的递归。

数据模型

    private Integer categoryId;

    private String categoryName;

    private Integer isRoot;

    private Integer categoryLevel;

    private Integer rootCategoryId;

    private Integer parentCategoryId;

    private String parentCategoryName;

以上是一个简单的类目的数据实体,主要要注意通过乐parentCategoryId实现了父子的关联。

数据库数据

我们可以很简单的通过父级的id获取其直接子级列表。但是如果我们想要通过某一父级id获取其直接下属和间接下属的(子,孙,曾孙等)列表呢?这就需要用到递归来实现。

实现方法

首先,我们在实体类下面加上这么一个属性。

public List<TCategory>childList=new ArrayList<TCategory>();//子Category列表

然后,我们编写xml文件中的ResultMap,如下。

<!-- 带有chlidList的map -->
    <resultMap id="TreeMap" type="com.qgranite.entity.TCategory">
        <id column="category_id" property="categoryId" jdbcType="INTEGER" />
        <result column="category_name" property="categoryName"
            jdbcType="VARCHAR" />
        <result column="category_remark" property="categoryRemark"
            jdbcType="VARCHAR" />
        <result column="category_type" property="categoryType"
            jdbcType="INTEGER" />
        <result column="is_root" property="isRoot" jdbcType="INTEGER" />
        <result column="category_level" property="categoryLevel"
            jdbcType="INTEGER" />
        <result column="root_category_id" property="rootCategoryId"
            jdbcType="INTEGER" />
        <result column="parent_category_id" property="parentCategoryId"
            jdbcType="INTEGER" />
        <result column="parent_category_name" property="parentCategoryName"
            jdbcType="VARCHAR" />
        <collection property="childList" column="category_id"
            ofType="com.qgranite.entity.TCategory" select="selectRecursionByParentCategoryId"></collection>
    </resultMap>

最后一句是关键,它说明了递归所需要调用的方法selectRecursionByParentCategoryId

然后我们来写这个递归方法。

<!-- 根据父键递归查询 -->
    <select id="selectRecursionByParentCategoryId" resultMap="TreeMap"
        parameterType="java.lang.Integer">
        select
        *
        from t_category
        where is_del=0
        and
        parent_category_id=#{_parameter,jdbcType=INTEGER}
    </select>

注意这边的resultMap就是上述定义的resultMap.

如果要递归获取所有的TCategory,我们只要获取所有category_type=1(即根类目),然后从根目录递归下去,注意这边的resultMap必须为TreeMap,才会触发递归。

<!-- 递归查询所有 -->
    <select id="selectRecursionAll" resultMap="TreeMap">
        select
        *
        from t_category
        where is_del=0
        and
       category_type=1
    </select>

接下来写后台调用方法。

/**
     * 根据特定父类递归查询所有子类
     * 
     * @param categoryId
     * @return
     */
    public List<TCategory> allCategoryRecursion() {
        return baseDao
                .findTList(
                        "TCategoryMapper.selectRecursionAll");
    }
/**
     * 根据特定父类递归查询所有子类
     * 
     * @param categoryId
     * @return
     */
    public List<TCategory> subCategoryListByParentId(int categoryId) {
        return baseDao
                .findTListByParam(
                        "TCategoryMapper.selectRecursionByParentCategoryId",
                        categoryId);
    }
 
/**
     * 根据categoryId获取子孙categoryId的id字符串,用逗号隔开
     * 
     * @param categoryId
     * @return
     */
    public String subCategoryStrByParentId(Integer categoryId) {
        String categoryStr = categoryId.toString();
        List<TCategory> categoryList = baseDao
                .findTListByParam(
                        "TCategoryMapper.selectRecursionByParentCategoryId",
                        categoryId);
        int size = categoryList.size();
        for (int i = 0; i < size; i++) {
            TCategory category = categoryList.get(i);
            categoryStr = categoryStr + "," + category.getCategoryId();
            if (!category.getChildList().isEmpty()) {
                Iterator<TCategory> it = category.getChildList().iterator();
                while (it.hasNext()) {
                    categoryStr = categoryStr + "," + it.next().getCategoryId();
                }
            }
        }
        return categoryStr;
    }

其中baseDao的代码如下。

package com.qgranite.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

/**
 * 所有dao基类
 * 
 * @author xdx
 *
 * @param <T>
 * @param <PK>
 */
@Repository("baseDao")
public class BaseDao<T, PK extends Serializable> {
    private Class<T> enetityClass;
    @Resource(name = "sqlSessionTemplate")
    private SqlSessionTemplate sqlSessionTemplate;

    // 构造方法,根据实例类自动获取实体类型,这边利用java的反射
    public BaseDao() {
        this.enetityClass = null;
        Class c = getClass();
        Type t = c.getGenericSuperclass();
        if (t instanceof ParameterizedType) {
            ParameterizedType p = (ParameterizedType) t;
            Type[] type = p.getActualTypeArguments();
            this.enetityClass = (Class<T>) type[0];
        }
    }

    /**
     * 获取实体
     * 
     * @param id
     * @return
     */
    public T getT(String sql, Object param) {
        return sqlSessionTemplate.selectOne(sql, param);
    }
    /**
     * 不带查询参数的列表
     * @param str
     * @return
     * @throws Exception
     */
    public List<T> findTList(String sql){
        return sqlSessionTemplate.selectList(sql);
    }

    /**
     * 带有参数的列表
     * 
     * @param str
     * @param param
     * @return
     * @throws Exception
     */
    public List<T> findTListByParam(String sql, Object param) {
        return sqlSessionTemplate.selectList(sql, param);
    }

    /**
     * 插入一条数据,参数是t
     * 
     * @param sql
     * @param t
     * @return
     */
    public int addT(String sql, T t) {
        return sqlSessionTemplate.insert(sql, t);
    }
    /**
     * 修改一条数据,参数是t
     * @param sql
     * @param t
     * @return
     */
    public int updateT(String sql,T t){
        return sqlSessionTemplate.update(sql, t);
    }
    /**
     * 删除t,参数是主键
     * @param sql
     * @param t
     * @return
     */
    public int deleteT(String sql,PK pk){
        return sqlSessionTemplate.delete(sql, pk);
    }
    /**
     * 根据param获取一个对象
     * @param sql
     * @param param
     * @return
     */
    public Object getObject(String sql,Object param){
        return sqlSessionTemplate.selectOne(sql,param);
    }
}
原文地址:https://www.cnblogs.com/roy-blog/p/7080258.html