前端兩個 `
-- 父類表
CREATE TABLE category_parent (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 子類表
CREATE TABLE category_child (
id INT PRIMARY KEY,
parent_id INT, -- 外鍵關聯父類
name VARCHAR(50),
FOREIGN KEY (parent_id) REFERENCES category_parent(id)
);
public class Parent {
private Integer id;
private String name;
private List children; // 非數據庫字段,用於前端渲染
// getter/setter
}
public class Child {
private Integer id;
private Integer parentId;
private String name;
// getter/setter
}
// MyBatis Mapper XML
// 返回 List
public Map> getChildMapByParentId() {
List
@GetMapping("/categories")
public ResponseEntity
// 1. 獲取數據
const { parents, childMap } = await api.getCategories();
// 2. 渲染一級下拉
parentSelect.innerHTML = parents.map(p =>
``
).join('');
// 3. 一級 change 事件更新二級
parentSelect.addEventListener('change', (e) => {
const parentId = Number(e.target.value);
const children = childMap[parentId] || [];
childSelect.innerHTML = children.map(c =>
``
).join('');
// 觸發二級 change 事件 (如有)
childSelect.dispatchEvent(new Event('change'));
});
// 4. 初始化觸發一次
parentSelect.dispatchEvent(new Event('change'));
| 場景 | 優化策略 |
|---|---|
| 數據量大 (萬級父類) | 不組裝全量 Map,改為 按需 AJAX:一級 change 時請求 `/children?parentId=xxx`,後端單表查詢返回子類列表。 |
| 數據極少且極少變 | 啟動時加載全量緩存到 Redis/本地內存,接口直接讀緩存,定時刷新。 |
| 樹形多級 (>2級) | 遞歸構建 TreeNode 結構,前端使用遞歸組件渲染 (如 Element UI el-cascader)。 |
| 頻繁增刪改 | 引入緩存失效策略:更新 DB 後同步刪除/更新 Redis 中的 childMap。 |
Java 實現二級聯動的核心是:**SQL 關聯查詢扁平化數據 → 內存中按 parentId 分組組裝 `Map