欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MyBatis實(shí)現(xiàn)三級(jí)樹查詢的示例代碼

 更新時(shí)間:2024年12月03日 09:13:23   作者:trymoLiu  
在實(shí)際項(xiàng)目開發(fā)中,樹形結(jié)構(gòu)的數(shù)據(jù)查詢是一個(gè)非常常見的需求,比如組織架構(gòu)、菜單管理、地區(qū)選擇等場(chǎng)景都需要處理樹形數(shù)據(jù),本文將詳細(xì)講解如何使用MyBatis實(shí)現(xiàn)三級(jí)樹形數(shù)據(jù)的查詢,需要的朋友可以參考下

引言

在實(shí)際項(xiàng)目開發(fā)中,樹形結(jié)構(gòu)的數(shù)據(jù)查詢是一個(gè)非常常見的需求。比如組織架構(gòu)、菜單管理、地區(qū)選擇等場(chǎng)景都需要處理樹形數(shù)據(jù)。本文將詳細(xì)講解如何使用MyBatis實(shí)現(xiàn)三級(jí)樹形數(shù)據(jù)的查詢,從數(shù)據(jù)庫設(shè)計(jì)到具體代碼實(shí)現(xiàn),幫助大家掌握樹形數(shù)據(jù)處理的核心要點(diǎn)。

數(shù)據(jù)庫設(shè)計(jì)

首先,我們需要設(shè)計(jì)一個(gè)合適的數(shù)據(jù)庫表結(jié)構(gòu)來存儲(chǔ)樹形數(shù)據(jù)。以下是一個(gè)典型的樹形表結(jié)構(gòu):

CREATE TABLE `sys_area` 
(  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
`parent_id` bigint(20) DEFAULT NULL COMMENT '父級(jí)ID', 
`name` varchar(50) NOT NULL COMMENT '地區(qū)名稱',
`level` int(11) NOT NULL COMMENT '層級(jí)(1:省份 2:城市 3:區(qū)縣)',
`sort` int(11) DEFAULT 0 COMMENT '排序號(hào)',  
`status` tinyint(4) DEFAULT 1 COMMENT '狀態(tài)(0:禁用 1:啟用)',  
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間', 
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間', 
PRIMARY KEY (`id`),  
KEY `idx_parent_id` (`parent_id`)) 
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='地區(qū)表';

實(shí)體類設(shè)計(jì)

接下來,我們需要?jiǎng)?chuàng)建對(duì)應(yīng)的實(shí)體類。為了支持樹形結(jié)構(gòu),我們需要添加一個(gè)children屬性來存儲(chǔ)子節(jié)點(diǎn):

@Data
public class Area implements Serializable {
      private static final long serialVersionUID = 1L;
          // 主鍵ID    
          private Long id;
          // 父級(jí)ID
          private Long parentId;
          // 地區(qū)名稱
          private String name;
          // 層級(jí)   
          private Integer level; 
          // 排序號(hào)   
          private Integer sort;   
          // 狀態(tài)   
          private Integer status;
          // 創(chuàng)建時(shí)間   
          private Date createTime;
          // 更新時(shí)間    
          private Date updateTime;  
          // 子節(jié)點(diǎn)列表   
          private List<Area> children;
      }

Mapper接口設(shè)計(jì)

創(chuàng)建AreaMapper接口,定義必要的查詢方法:

@Mapper
public interface AreaMapper {
    /**     
    * 查詢所有地區(qū)數(shù)據(jù)    
    * @return 地區(qū)列表     */  
    List<Area> selectAllAreas(); 
    /**     
    * 根據(jù)父ID查詢子地區(qū)     
    * @param parentId 父級(jí)ID     
    * @return 子地區(qū)列表     */   
    List<Area> selectAreasByParentId(Long parentId);        
    /**    
    * 查詢指定層級(jí)的地區(qū)     
    * @param level 層級(jí)    
    * @return 地區(qū)列表     */  
    List<Area> selectAreasByLevel(Integer level);
}

XML映射文件實(shí)現(xiàn)

在resources目錄下創(chuàng)建AreaMapper.xml文件:

<?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.example.mapper.AreaMapper">
    <!-- 基礎(chǔ)列 -->  
    <sql id="Base_Column_List"> 
        id, parent_id, name, level, sort, status, create_time, update_time   
    </sql>       
    <!-- 查詢所有地區(qū) --> 
    <select id="selectAllAreas" resultType="com.example.entity.Area"> 
        SELECT   <include refid="Base_Column_List"/>    FROM sys_area 
        WHERE status = 1      
        ORDER BY sort ASC, id ASC   
    </select>       
    <!-- 根據(jù)父ID查詢子地區(qū) -->  
    <select id="selectAreasByParentId" resultType="com.example.entity.Area"> 
        SELECT     <include refid="Base_Column_List"/>     FROM sys_area        
        WHERE status = 1        
        AND parent_id = #{parentId}       
        ORDER BY sort ASC, id ASC   
    </select>      
    <!-- 查詢指定層級(jí)的地區(qū) -->   
    <select id="selectAreasByLevel" resultType="com.example.entity.Area">  
        SELECT     <include refid="Base_Column_List"/>    FROM sys_area        
        WHERE status = 1     
        AND level = #{level}    
        ORDER BY sort ASC, id ASC  
    </select>
</mapper>

Service層實(shí)現(xiàn)

創(chuàng)建Service接口及其實(shí)現(xiàn)類:

@Service
@Slf4j
public class AreaServiceImpl implements AreaService {
    @Autowired
    private AreaMapper areaMapper; 
    @Override
    public List<Area> buildAreaTree() { 
        // 查詢所有地區(qū)數(shù)據(jù) 
        List<Area> allAreas = areaMapper.selectAllAreas(); 
        // 構(gòu)建樹形結(jié)構(gòu)
        return buildTree(allAreas);
    } 
    /**
    * 構(gòu)建樹形結(jié)構(gòu) 
    * @param areas 地區(qū)列表 
    * @return 樹形結(jié)構(gòu)的地區(qū)列表 
    */ 
    private List<Area> buildTree(List<Area> areas) { 
        List<Area> trees = new ArrayList<>(); 
        // 獲取所有根節(jié)點(diǎn)(省份)
        areas.stream().filter(area -> area.getLevel() == 1) .forEach(province -> { 
            // 設(shè)置省份的子節(jié)點(diǎn)(城市) 
            List<Area> cities = getChildren(areas, province.getId()); 
            province.setChildren(cities); 
            // 設(shè)置城市的子節(jié)點(diǎn)(區(qū)縣)
            cities.forEach(city -> { List<Area> districts = getChildren(areas, city.getId());   
                city.setChildren(districts);  
            });
            trees.add(province);
        });
        return trees; 
    } 
    /**
    * 獲取子節(jié)點(diǎn) 
    * @param areas 所有地區(qū)列表 
    * @param parentId 父級(jí)ID 
    * @return 子節(jié)點(diǎn)列表
    */ 
    private List<Area> getChildren(List<Area> areas, Long parentId) { 
        return areas.stream().filter(area -> Objects.equals(area.getParentId(), parentId)) 
        .collect(Collectors.toList()); 
    }
}

Controller層實(shí)現(xiàn)

最后,創(chuàng)建Controller處理前端請(qǐng)求:

@RestController@RequestMapping("/api/areas")
public class AreaController {   
    @Autowired   
    private AreaService areaService;    
    /**    
    * 獲取地區(qū)樹形數(shù)據(jù)     */ 
    @GetMapping("/tree")   
    public ResponseResult<List<Area>> getAreaTree() { 
        try {       
            List<Area> trees = areaService.buildAreaTree();   
            return ResponseResult.success(trees);    
        } catch (Exception e) {   
            log.error("獲取地區(qū)樹形數(shù)據(jù)失敗", e);    
            return ResponseResult.error("獲取地區(qū)樹形數(shù)據(jù)失敗");     
        }  
   }
}

性能優(yōu)化建議

  • 緩存優(yōu)化
  • 考慮使用Redis緩存樹形數(shù)據(jù),因?yàn)榈貐^(qū)數(shù)據(jù)變動(dòng)頻率較低
  • 可以設(shè)置合理的緩存過期時(shí)間,如24小時(shí)
@Service
public class AreaServiceImpl implements AreaService {
    @Autowired   
    private RedisTemplate<String, List<Area>> redisTemplate; 
    private static final String AREA_TREE_KEY = "AREA:TREE";  
    private static final long CACHE_TIMEOUT = 24; 
    // 小時(shí)   
    @Override   
    public List<Area> buildAreaTree() {
        // 先從緩存獲取  
        List<Area> cacheTree = redisTemplate.opsForValue().get(AREA_TREE_KEY);   
        if (cacheTree != null) {   
            return cacheTree;  
        }               
        // 緩存未命中,查詢數(shù)據(jù)庫并構(gòu)建樹    
        List<Area> trees = buildTreeFromDb();       
        // 放入緩存    
        redisTemplate.opsForValue().set(AREA_TREE_KEY, trees, CACHE_TIMEOUT, TimeUnit.HOURS);                return trees;
    }
}

2. SQL優(yōu)化

  • 適當(dāng)添加索引:parent_id, level, status等字段
  • 考慮使用批量查詢替代循環(huán)查詢

3. 內(nèi)存優(yōu)化

  • 使用Stream API時(shí)注意及時(shí)關(guān)閉
  • 合理設(shè)置集合的初始容量
  • 及時(shí)釋放不再使用的對(duì)象引用

總結(jié)

通過本文的講解,我們實(shí)現(xiàn)了一個(gè)完整的三級(jí)樹形數(shù)據(jù)查詢功能。關(guān)鍵要點(diǎn)包括:

  • 合理的數(shù)據(jù)庫表設(shè)計(jì),包含必要的字段和索引
  • 清晰的實(shí)體類設(shè)計(jì),支持樹形結(jié)構(gòu)
  • MyBatis映射文件的編寫,實(shí)現(xiàn)基礎(chǔ)的數(shù)據(jù)查詢
  • Service層的樹形構(gòu)建算法實(shí)現(xiàn)
  • 性能優(yōu)化和緩存的使用

到此這篇關(guān)于MyBatis實(shí)現(xiàn)三級(jí)樹查詢的示例代碼的文章就介紹到這了,更多相關(guān)MyBatis三級(jí)樹查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot調(diào)用第三方接口的幾種方式小結(jié)

    SpringBoot調(diào)用第三方接口的幾種方式小結(jié)

    在項(xiàng)目中調(diào)用第三方接口時(shí),確實(shí)需要根據(jù)項(xiàng)目的技術(shù)棧、架構(gòu)規(guī)范以及具體的業(yè)務(wù)需求來選擇最適合的調(diào)用方式,下面我們就介紹幾種調(diào)用第三方接口的實(shí)現(xiàn)方式以及代碼示例,需要的朋友可以參考下
    2024-07-07
  • 在Spring中如何注入動(dòng)態(tài)代理Bean

    在Spring中如何注入動(dòng)態(tài)代理Bean

    這篇文章主要介紹了在Spring中如何注入動(dòng)態(tài)代理Bean問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 移動(dòng)指定文件夾內(nèi)的全部文件

    移動(dòng)指定文件夾內(nèi)的全部文件

    移動(dòng)指定文件夾內(nèi)的全部文件
    2009-01-01
  • mybatis中的if-test判斷解讀

    mybatis中的if-test判斷解讀

    在使用MyBatis進(jìn)行條件判斷時(shí),如果條件中涉及到字符與數(shù)字的比較,需要特別注意比較方式,例如,在<if>標(biāo)簽中,比較數(shù)字“1”時(shí),應(yīng)將其寫在雙引號(hào)中,或者使用.toString()方法,避免直接使用字符'1'進(jìn)行比較
    2024-11-11
  • 深入了解SparkSQL中數(shù)據(jù)的加載與保存

    深入了解SparkSQL中數(shù)據(jù)的加載與保存

    這篇文章主要為大家詳細(xì)介紹了SparkSQL中數(shù)據(jù)的加載與保存的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解下
    2023-11-11
  • 淺析java雙向冒泡排序算法

    淺析java雙向冒泡排序算法

    這篇文章主要介紹了淺析java雙向冒泡排序算法,并附上源碼,需要的朋友可以參考下
    2015-02-02
  • java 實(shí)現(xiàn)圖片合成,并添加文字

    java 實(shí)現(xiàn)圖片合成,并添加文字

    這篇文章主要介紹了java 實(shí)現(xiàn)圖片合成,并添加文字的示例,幫助大家更好的利用Java處理圖片,感興趣的朋友可以了解下
    2020-12-12
  • java中int、double、char等變量的取值范圍詳析

    java中int、double、char等變量的取值范圍詳析

    這篇文章主要給大家介紹了關(guān)于java中int、double、char等變量取值范圍的相關(guān)資料,每個(gè)變量都給出了詳細(xì)的實(shí)例代碼,對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-10-10
  • java ThreadLocal線程局部變量常用方法使用場(chǎng)景示例詳解

    java ThreadLocal線程局部變量常用方法使用場(chǎng)景示例詳解

    這篇文章主要介紹了為大家java ThreadLocal線程局部變量常用方法使用場(chǎng)景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Xml中使用foreach遍歷對(duì)象實(shí)現(xiàn)代碼

    Xml中使用foreach遍歷對(duì)象實(shí)現(xiàn)代碼

    這篇文章主要介紹了Xml中使用foreach遍歷對(duì)象實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12

最新評(píng)論