递归调用的应用场景常常出现在多级嵌套的情况,比如树形的菜单。下面通过一个简单的例子来实现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);
}
}

mysql+mybatis递归调用的更多相关文章

  1. Java Spring+Mysql+Mybatis 实现用户登录注册功能

    前言: 最近在学习Java的编程,前辈让我写一个包含数据库和前端的用户登录功能,通过看博客等我先是写了一个最基础的servlet+jsp,再到后来开始用maven进行编程,最终的完成版是一个 Spri ...

  2. mysql中递归树状结构<转>

    在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...

  3. mysql 树结构递归处理

    日常开发中我们经常会遇到树形结构数据处理,一般表结构通常会常用id,pid这种设计方案. 之前用oracle.sqlServer数据库,用相应的语法即可获取树形结构数据(oracel:connect ...

  4. springboot学习笔记:8. springboot+druid+mysql+mybatis+通用mapper+pagehelper+mybatis-generator+freemarker+layui

    前言: 开发环境:IDEA+jdk1.8+windows10 目标:使用springboot整合druid数据源+mysql+mybatis+通用mapper插件+pagehelper插件+mybat ...

  5. springboot学习笔记:10.springboot+atomikos+mysql+mybatis+druid+分布式事务

    前言 上一篇文章我们整合了springboot+druid+mybatis+mysql+多数据源: 本篇文章大家主要跟随你们涛兄在上一届基础上配置一下多数据源情况下的分布式事务: 首先,到底啥是分布式 ...

  6. Python-函数的递归调用

    递归调用顾名思义即在函数内部调用函数(自己调用自己),通常用它来计算阶乘,累加等   注意: - 必须有最后的默认结果 if n ==0,(不能一直调用自己,如果没有可能会造成死循环) - 递归参数必 ...

  7. mybatis动态调用表名和字段名

    以后慢慢启用个人博客:http://www.yuanrengu.com/index.php/mybatis1021.html 一直在使用Mybatis这个ORM框架,都是使用mybatis里的一些常用 ...

  8. 关于C++的递归调用(n的阶乘为例)

    C++,是入门编程界的一门初期的语言.今天我们浅谈一下有关C++的递归调用. 在没有继承,多态,封装之前,C++几乎看成是C语言,除了一些简单的输出和头文件. 具体代码实现如下: #include&l ...

  9. java中父类与子类, 不同的两个类中的因为构造函数由于递归调用导致栈溢出问题

    /* 对于类中对成员变量的初始化和代码块中的代码全部都挪到了构造函数中, 并且是按照java源文件的初始化顺序依次对成员变量进行初始化的,而原构造函数中的代码则移到了构造函数的最后执行 */ impo ...

随机推荐

  1. kickstart 实现批量安装centos7.x系统

    1.1 安装系统的方法 l  光盘(ISO文件,光盘的镜像文件)===>>每一台物理机都得给一个光驱,如果用外置光驱的话,是不是每台机器都需要插一下 l  U盘:ISO镜像刻录到U盘==& ...

  2. C#中float, double的精度问题

    在工作中我发现了一个C#浮点数的精度问题,以下的程序运行结果并未得到我预期的结果: view source print? 01 namespace FloatTest 02 03     class ...

  3. 休息,归类一下CSS初级的东西

    css基础的东西集中体现在了"磊盒子"这一个枯燥无味的东西上面,灵活的运用盒子的内外边距,浮动,定位以及一些基础的属性,将一个静态的页面变得磊出来,这是CSS基础的练习. 在css ...

  4. Vue组件库 VV-UI 开始接受PR啦,有兴趣小伙伴可以一起参与开源哦。

    前言: 刚开源出来的VV-UI目前刚刚起步,组件不是很多,非常欢迎大家的pr和Star.项目地址: https://github.com/VV-UI/VV-UI演示地址: https://vv-ui. ...

  5. Python之random

    random 伪随机数生成模块.如果不提供seed,默认使用系统时间. 使用相同seed,可获得相同的随机数序列,常用于测试. >>> from random import * &g ...

  6. Python StringIO与BytesIO、类文件对象

    StringIO与BytesIO StringIO与BytesIO.类文件对象的用途,应用场景,优.缺点. StringIO StringIO 是io 模块中的类,在内存中开辟的一个文本模式的buff ...

  7. [拓扑排序]Ordering Tasks UVA - 10305

    拓扑排序模版题型: John has n tasks to do.Unfortunately, the tasks are not independent and the execution of o ...

  8. 开源项目 log4android 使用方式详解

    话不多说, 直接上主题. log4android 是一个类似于log4j的开源android 日志记录项目. 项目基于 microlog 改编而来, 新加入了对文件输出的各种定义方式. 项目地址: 点 ...

  9. head first python菜鸟学习笔记(第四章)

    1,p124,错误:NameError: name 'print_lol' is not defined 要想文件内如图显示,需要把调用BIF print()改为调用第二章的nester模块中的pri ...

  10. A:分段函数-poj

    A:分段函数 总时间限制:  1000ms 内存限制:  65536kB 描述 编写程序,计算下列分段函数y=f(x)的值. y=-x+2.5; 0 <= x < 5 y=2-1.5(x- ...