好久沒有寫博客了,就分享一些亂七八糟的東西吧!
1.oracle遞回查詢
大家應該使用有的時候會使用遞回查詢資料庫選單的吧,比如下面這樣的(偷的圖)( ̄▽ ̄)ノ

這種一般是業務管理系統比較多,比如選單樹,權限樹或者機構樹等等,從資料庫中查詢出的資料,然后使用java代碼構建成前端需要的樹的結構,然后回傳給前端,ui組件渲染展示
所以通常我們會有下面這種的表(oracle版本建表陳述句可以自己做修改),有著父節點和位元組點的關系,就是id和parent_id
CREATE TABLE jrbac_menu (
id number(8) primary key not null , --主鍵id
real_name varchar(50) NULL,
parent_id varchar(50) NULL, -- 父級選單id
url_path varchar(500) NOT NULL,
icon varchar2(20) null,
torder varchar(50) NOT NULL
);
INSERT INTO jrbac_menu VALUES (1, 'Forms', null, 'forms.html', 'fa fa-edit', '0');
INSERT INTO jrbac_menu VALUES (2, 'UI Elements', null, 'Elements.html', 'fa fa-wrench', '1');
INSERT INTO jrbac_menu VALUES (3, 'Buttons', '2', 'buttons.html', 'Buttons', '0');
INSERT INTO jrbac_menu VALUES (4, 'Icons', '2', 'icons.html', 'Icons', '1');
INSERT INTO jrbac_menu VALUES (5, 'Multi-Level Dropdown', null, 'Dropdown.html', 'fa fa-sitemap', '2');
INSERT INTO jrbac_menu VALUES (6, 'Second Level Item', '5', 'second.html', 'Second', '0');
INSERT INTO jrbac_menu VALUES (7, 'Third Level', '5', 'Third.html', 'Third', '1');
INSERT INTO jrbac_menu VALUES (8, 'Third Level Item', '7', 'third.html', 'Third Level Item', '0');
至于java代碼的話,會大概像下面這種寫法(比較懶,代碼是隨便找的),簡而言之就是:先找出所有的一級選單,然后遍歷每個一級選單,找到每一個一級選單的二級選單,再用遞回的方式找到三級選單,四級選單.....
public void testQueryMenuList() { // 所有的選單資料 List<Menu> rootMenu = menuDao.queryMenuList(null); // 結果樹 List<Menu> menuList = new ArrayList<Menu>(); // 先找到所有的一級選單 for (int i = 0; i < rootMenu.size(); i++) { // 一級選單沒有parentId if (StringUtils.isBlank(rootMenu.get(i).getParentId())) { menuList.add(rootMenu.get(i)); } } // 為一級選單設定子選單,getChild是遞回呼叫的 for (Menu menu : menuList) { menu.setChildMenus(getChild(menu.getId(), rootMenu)); } Map<String,Object> jsonMap = new HashMap<>(); jsonMap.put("menu", menuList); System.out.println(JSON.toJSONString(jsonMap)); } /** * 遞回查找子選單 * * @param id * 當前選單id * @param rootMenu * 要查找的串列 * @return */ private List<Menu> getChild(String id, List<Menu> rootMenu) { // 子選單 List<Menu> childList = new ArrayList<>(); for (Menu menu : rootMenu) { // 遍歷所有節點,將父選單id與傳過來的id比較 if (StringUtils.isNotBlank(menu.getParentId())) { if (menu.getParentId().equals(id)) { childList.add(menu); } } } // 把子選單的子選單再回圈一遍 for (Menu menu : childList) {// 沒有url子選單還有子選單 if (StringUtils.isBlank(menu.getUrl())) { // 遞回 menu.setChildMenus(getChild(menu.getId(), rootMenu)); } } // 遞回退出條件 if (childList.size() == 0) { return null; } return childList; }
我以前也是這樣的寫的,這種寫法就很煩,后來我就查了一下資料,可以直接使用sql遞回查詢
start with ... connect by prior 語法來實作遞回查詢,使用了這種語法之后,一條sql就實作上面一堆代碼的功能了:
例如表中原始資料:
select * from jrbac_menu;

我們想要查詢real_name為'Multi-Level Dropdown' 的一級選單下的所有子選單,我們把這個一級選單當作一個根節點
從根節點向下遞回查詢:select * from jrbac_menu start with real_name='Multi-Level Dropdown' connect by prior id = parent_id;

sql使用說明,假如下面的sql是查詢所有的子選單節點,如果最后是parent_id=id,那么就是查詢當前根節點的所有父級節點;

所以我覺得使用start with connect ... by prior 語法必須的兩個條件:1.oracle資料庫 2.選單有個公共的根節點,或者只是查詢其中其中一部分子樹節點;
2.orcale分頁查詢
在mysql中我們可以使用limit關鍵字就很容易的實作了分頁,但是在oracle中,語法就比較長一點
1.首先前端傳遞分頁引數,page和pageSize
2.我們需要將他轉為起始條數和終止條數:startSize=(page-1)*pageSize+1 endSize=page*pageSize
3.設定到oracle的分頁陳述句中:
SELECT * FROM ( SELECT ROWNUM rowno, t.* FROM emp t WHERE hire_date BETWEEN TO_DATE ('20060501', 'yyyymmdd') AND ROWNUM <= #{endSize} ) table_alias WHERE table_alias.rowno >= #{startSize};
有興趣的可以自己開發一個基于mybatis+oracle的分頁插件:參考這里
不過這里是mysql的,可以將我上面寫第2點和第3點丟過去,稍微魔改一下就行了
為什么需要自己開發一個分頁插件呢?不是有開源的pageHelper么,哎,一言難盡,那種很老的專案的話我都不敢去引入第三方依賴,不要本來還能跑的,結果引入了第三方依賴出現奇怪的問題(╯—﹏—)╯(┷━━━┷
還有就是搞不懂為什么有的人就能每次都習慣用這么麻煩的分頁陳述句,我第一次看的時候都看的有點懵逼,還是在不影響現在的功能的前提下,自己動手豐衣足食吧
--------------以上皆原創,給未來的自己留下一點學習的痕跡!--------
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/319565.html
標籤:Java
上一篇:JVM簡明筆記1:JVM 概述
