遞歸的實際業務場景之MySQL 遞歸查詢


喜歡就點個贊唄!
源碼<--請點擊此處查看

引入

當我看到一些評論時,例如下面的樣子。我挺好奇這個功能是怎么樣做出來的。進過查閱資料,發現這其實是 MySQL 的遞歸操作。下面就讓我操作一下怎么實現 MySQL 的遞歸查詢。

設計數據庫

觀察這種數據庫設計,你會發現他都有一個父節點,一直到根節點,所以我們設計數據庫的時候,應該設置一個 parentid 字段。所以,我們可以得到以下的數據庫。

sql 腳本如下

CREATE TABLE digui(
	id INT(11) NOT null auto_increment,
	msg VARCHAR(255) not NULL COMMENT '評論的內容',
	parentid int(11) not null COMMENT '上一條',
	PRIMARY KEY(id)
)ENGINE=INNODB auto_increment = 100 DEFAULT CHARSET=utf8mb4;

INSERT into `digui`(msg, parentid) VALUES ('A', 0);
INSERT into `digui`(msg, parentid) VALUES('B', 1);
INSERT into `digui`(msg, parentid) VALUES('D', 3);
INSERT into `digui`(msg, parentid) VALUES('C', 2);

其實實現 MySQL 的遞歸查詢方法有很多

  1. 使用 MySQL 存儲過程
  2. 應用層代碼遞歸
  3. MyBatis 的 collection 標簽

方案1 應用層代碼遞歸

//應用層遞歸查詢
@Override
public List<Digui> getAll(int parent) {
    List<Digui> deptVosList=new ArrayList<>();
    QueryWrapper queryWrapper = new QueryWrapper();
    queryWrapper.eq("parentid", parent);
    List<Digui> list1 = list(queryWrapper);
    for (Digui digui: list1) {
        Digui digui1 = new Digui();
        digui1.setId(digui.getId());
        digui1.setMsg(digui.getMsg());
        digui1.setParentid(digui.getParentid());
        // 此處遞歸調用賦值
        digui1.setDiguiList(getAll(digui.getId()));
        deptVosList.add(digui1);
    }
    return deptVosList;

}

方案2 MyBatis 的 collection 標簽

 <resultMap id="RecursiveMap" type="com.example.lsbdigui.entity.Digui">
        <result property="id" column="id"/>
        <result property="msg" column="msg"/>
        <result property="parentid" column="parentid"/>
        <collection property="diguiList" ofType="com.example.lsbdigui.entity.Digui"
                    select="com.example.lsbdigui.mapper.DiguiMapper.getAllBySQL"
                    column="id"/>
</resultMap>
<select id="getAllBySQL" resultMap="RecursiveMap">
    select *
    from digui
    where parentid = #{parent}
</select>

使用<collection><select>標簽實現 sql 遞歸查詢。

結果

{
    "code": 200,
    "msg": "正確返回",
    "date": [
        {
            "id": 100,
            "msg": "A",
            "parentid": 0,
            "diguiList": [
                {
                    "id": 101,
                    "msg": "B",
                    "parentid": 100,
                    "diguiList": [
                        {
                            "id": 103,
                            "msg": "C",
                            "parentid": 101,
                            "diguiList": [
                                {
                                    "id": 102,
                                    "msg": "D",
                                    "parentid": 103,
                                    "diguiList": []
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

對比

建議

應用層可以一次查詢全部數據,然后再遞歸找出需要的數據,這樣可以減少數據庫查詢,性能更佳。

參考

關注微信公眾號,隨時移動端閱讀

公眾號.jpg


免責聲明!

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



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