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); } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM