基于springboot jpa thymeleaf的java無限分類的樣式及表格創(chuàng)建見:
http://tjegd.cn/news/show/866.html
一. 建立實(shí)體文件如下:
@Entity public class Sorts { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String sortName; private int parentId; private String sortPath; private int levels; private int orders; @Transient private String space; //列表查詢時(shí), 前面的空間隔 @Transient private String oldSortPath; @Transient private String newSortPath; public String getSortName() { return sortName; } public void setSortName(String sortName) { this.sortName = sortName; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getParentId() { return parentId; } public void setParentId(int parentId) { this.parentId = parentId; } public String getSortPath() { return sortPath; } public void setSortPath(String sortPath) { this.sortPath = sortPath; } public int getLevels() { return levels; } public void setLevels(int levels) { this.levels = levels; } public int getOrders() { return orders; } public void setOrders(int orders) { this.orders = orders; } public String getSpace() { return space; } public void setSpace(String space) { this.space = space; } public String getOldSortPath() { return oldSortPath; } public void setOldSortPath(String oldSortPath) { this.oldSortPath = oldSortPath; } public String getNewSortPath() { return newSortPath; } public void setNewSortPath(String newSortPath) { this.newSortPath = newSortPath; } }
二. 建立Resotitory接口
public interface SortsRepository extends JpaRepository<Sorts,Integer>, JpaSpecificationExecutor<Sorts> { @Query(value=" select * from sorts where parentId = ?1 order by orders asc ",nativeQuery=true ) public ArrayList<Sorts> selectByParentId(Integer id) ; @Query(value="select * from sorts where parentId = :#{#sorts.parentId} and sortName = :#{#sorts.sortName}",nativeQuery=true ) public Sorts selectBySortNameAndParendId(@Param("sorts") Sorts sorts); @Query(value = " select * from sorts where parentId = :#{#sorts.parentId} and sortName = :#{#sorts.sortName} " + "and id <> :#{#sorts.id}",nativeQuery = true) public Sorts selectSortsByParentIdSortName(@Param("sorts") Sorts sorts); @Query(value = " update sorts set sortPath = replace(sortPath,:#{#sorts.oldSortPath},:#{#sorts.newSortPath}) where\n" + " sortPath like concat('%',:#{#sorts.oldSortPath},'%') and id <> :#{#sorts.id}", nativeQuery = true) @Transactional @Modifying public int updateAllChildSorts(@Param("sorts")Sorts sorts); @Query(value = " update sorts set levels = length(sortPath)- length(replace(sortPath,',','')) - 1 where\n" + " sortPath like concat('%',:#{#sorts.newSortPath},'%') and id <> :#{#sorts.id}", nativeQuery = true) @Transactional @Modifying public int updateAllChildSortsLevels(@Param("sorts")Sorts sorts); @Query(value = "delete from sorts where sortPath like concat ('%',','+ :id +',','%')", nativeQuery = true) @Transactional @Modifying public int deleteAllSortsById(@Param("id") Integer id); }
三. 建立service接口
public interface SortsService { public ArrayList<Sorts> getChildren(int parentId, String space, ArrayList<Sorts> arr); public StringBuffer selectTrees(int pid,String selectName,int currentId); public String addSorts(Sorts sorts); public String updateSorts(Sorts sorts); public String deleteAllSortsById(Integer id); }
四. 實(shí)現(xiàn)SortsService接口類
@Service("sortsService") public class SortsServiceImpl implements SortsService { @Autowired private SortsRepository sortsDao; private static ArrayList<Sorts> all; //存儲(chǔ)所有的查詢子類數(shù)據(jù) @Override //parentId: 父類 ID, 查詢當(dāng)前類別下的所有子類 //space : // 類別前面的空隔 public ArrayList<Sorts> getChildren(int parentId, String space, ArrayList<Sorts> arr){ if(arr == null){ //第一次查詢 System.out.println(parentId); arr = sortsDao.selectByParentId(parentId); all = new ArrayList<>(); //第一次時(shí), 初始化, 避免刷新調(diào)用重新添加信息 } if(arr != null){ for(Sorts sorts : arr){ //根據(jù)級(jí)別不一樣, 在前面加上相應(yīng)的分隔符 int levels = sorts.getLevels(); if(levels == 1){ sorts.setSpace(""); } else if(levels == 2){ space = " |---->"; sorts.setSpace(space); } else{ sorts.setSpace(space); } all.add(sorts); //將所有的信息都加到all里, 并增加一個(gè)space字段 parentId = sorts.getId(); ArrayList<Sorts> arr_child = sortsDao.selectByParentId(parentId); if(arr_child != null){ getChildren(parentId," |" + space,arr_child); } } } return all; } @Override //得到無限分類的select下拉列表 //pid : 父id //selectName select的名字 //currenId : 被選擇的id, 沒有的話,傳遞0 public StringBuffer selectTrees(int pid, String selectName, int currentId) { StringBuffer sBuffer = new StringBuffer(); ArrayList<Sorts> results = getChildren(pid,"",null); if(results != null){ sBuffer.append("<select name='"+selectName+"'>\n"); sBuffer.append("<option value='0'>一級(jí)類別</option> \n"); for(Sorts sorts : results){ int id = sorts.getId(); if( id == currentId){ sBuffer.append("<option value='"+id+"' style='background:#E20A0A; color:#fff;' selected>"+ sorts.getSpace() + sorts.getSortName() + "</option> \n"); } else{ sBuffer.append("<option value='"+id+"'>"+ sorts.getSpace() + sorts.getSortName() + "</option> \n"); } } sBuffer.append("</select>\n"); } return sBuffer; } @Override public String addSorts(Sorts sorts) { //判斷類名不能為空 if(sorts.getSortName().equals("")) { return "<script>alert('類別名稱不能為空');history.back();</script>"; } //判斷同一級(jí)下不能重復(fù)的名稱 if(sortsDao.selectBySortNameAndParendId(sorts) != null){ return "<script>alert('父類下已存在相同類別!!!');history.back();</script>"; } //設(shè)置level, sortpath 信息 begin sorts.setLevels(1); sorts.setSortPath("0,"); if(sorts.getParentId() != 0){ //最頂級(jí)時(shí)使用默認(rèn)設(shè)置值, 否則根據(jù)父級(jí)來決定 Sorts getSorts = sortsDao.getOne(sorts.getParentId()); sorts.setLevels(getSorts.getLevels() + 1); sorts.setSortPath(getSorts.getSortPath()); //暫時(shí)為父級(jí)sortPath, 當(dāng)添加后, 再更新,將當(dāng)前的id鏈接上 } //將信息添加到數(shù)據(jù)庫(kù)sorts sortsDao.save(sorts); //sorts中會(huì)更新為新增加的id主鍵 //更新sortPath 到數(shù)據(jù)庫(kù) sorts.setSortPath(sorts.getSortPath() + sorts.getId() + ","); sortsDao.save(sorts); return "<script>alert('添加成功');location.href='/admin/sorts/list';</script>"; } @Override public String updateSorts(Sorts sorts) { //判斷類名不能為空 if(sorts.getSortName().equals("")) { return "<script>alert('類別名稱不能為空');history.back();</script>"; } //根據(jù)id得到原來的信息 Sorts oldSorts = sortsDao.getOne(sorts.getId()); int oldPid = oldSorts.getParentId(); //原父id String oldSortPath = oldSorts.getSortPath(); //判斷類別名稱是否重復(fù) Sorts exitSorts = sortsDao.selectSortsByParentIdSortName(sorts); if(exitSorts != null){ return "<script>alert('類別已經(jīng)存在,請(qǐng)更換類別名稱');history.back();</script>"; } if(oldPid == sorts.getParentId()){ //父id不變, 則parentid, level都不需要修改 sorts.setSortPath(oldSorts.getSortPath()); sorts.setLevels(oldSorts.getLevels()); sortsDao.save(sorts); } else if(sorts.getParentId() == 0){ //移動(dòng)到一級(jí)類別 sorts.setSortPath("0," + sorts.getId() + ","); sorts.setLevels(1); //更新當(dāng)前類別信息 sortsDao.save(sorts); //更新所有的修改類別的子類sortPath Sorts sort1 = new Sorts(); sort1.setOldSortPath(oldSortPath); sort1.setNewSortPath(sorts.getSortPath()); sort1.setId(sorts.getId()); sortsDao.updateAllChildSorts(sort1); //更新所有子類的層級(jí) sortsDao.updateAllChildSortsLevels(sort1); } else{ //判斷是否移到到了子類另, 這樣是不允許的, 中間會(huì)斷層 //得到當(dāng)前父類的path Sorts parentSorts = sortsDao.getOne(sorts.getParentId()); String parentSortPath = parentSorts.getSortPath(); if(parentSortPath.indexOf(oldSortPath) >= 0){ return "<script>alert('類別不能選擇為原父類的子類');history.back();</script>"; } else{ //父類更新到上一級(jí)或者其它的類別下, 那么該類別下所有的子類都需要更新父級(jí)sortpath //新的sortpath String newSortPath = parentSortPath + sorts.getId() + ","; int newLevel = parentSorts.getLevels() + 1; sorts.setSortPath(newSortPath); sorts.setLevels(newLevel); sortsDao.save(sorts); //更新所有的修改類別的子類 //更新所有的修改類別的子類sortPath //更新所有的修改類別的子類sortPath Sorts sort1 = new Sorts(); sort1.setOldSortPath(oldSortPath); sort1.setNewSortPath(sorts.getSortPath()); sort1.setId(sorts.getId()); sortsDao.updateAllChildSorts(sort1); //更新所有子類的層級(jí) sortsDao.updateAllChildSortsLevels(sort1); } } return "<script>alert('修改成功');location.href='/admin/sorts/list';</script>"; } //刪除所有的子類 @Override public String deleteAllSortsById(Integer id) { sortsDao.deleteAllSortsById(id); return "<script>alert('刪除成功');location.href='/admin/sorts/list';</script>"; } }
五. 控制器實(shí)現(xiàn)如下:
@Controller public class SortsController { @Autowired @Qualifier("sortsService") private SortsService sortsService; @Autowired private SortsRepository sortsDao; @GetMapping(value = "/admin/sorts/add") public String add(@RequestParam(defaultValue = "0") Integer parentId, Model model){ model.addAttribute("selectTrees",sortsService.selectTrees(0,"parentId",parentId)); return "admin/sorts/add"; } @PostMapping(value = "/admin/sorts/addSave") @ResponseBody public String addSave(Sorts sorts){ return sortsService.addSorts(sorts); } @GetMapping(value = "/admin/sorts/list") public String list(Model model){ ArrayList<Sorts> all = sortsService.getChildren(0,"",null); model.addAttribute("all",all); return "admin/sorts/list"; } @GetMapping(value = "/admin/sorts/update") public String update(@RequestParam(defaultValue = "0") Integer id,Model model){ Sorts sorts = sortsDao.getOne(id); model.addAttribute("sorts",sorts); model.addAttribute("selectTrees",sortsService.selectTrees(0,"parentId",sorts.getParentId())); return "/admin/sorts/update"; } @PostMapping(value = "/admin/sorts/updateSave") @ResponseBody public String updateSave(Sorts sorts){ return sortsService.updateSorts(sorts); } @GetMapping(value = "/admin/sorts/del") @ResponseBody public String del(@RequestParam(defaultValue = "0") Integer id){ return sortsService.deleteAllSortsById(id); } }
六. 對(duì)應(yīng)的視圖文件如下:
添加視圖:
<form action="/admin/sorts/addSave" method="post"> <li> <label>父級(jí)類別:</label> [(${selectTrees})] </li> <li> <lable>類別名稱: </lable> <input type="text" name="sortName" /> </li> <li> <label>排序: </label> <input type="number" name="orders" value="1" /> </li> <li> <input type="submit"/> </li> </form>
修改視圖:
<form action="/admin/sorts/updateSave" method="post" th:object="${sorts}"> <li> <label>父級(jí)類別:</label> [(${selectTrees})] </li> <li> <lable>類別名稱: </lable> <input type="text" th:field="*{sortName}"/> </li> <li> <label>排序: </label> <input type="number" th:field="*{orders}"/> </li> <li> <input type="hidden" th:field="*{id}"> <input type="submit"/> </li> </form>
列表視圖:
<table> <tr> <td colspan="4"> <a href="/admin/sorts/add">添加一級(jí)類別</a> </td> </tr> <tr> <td>ID</td> <td>類別名稱</td> <td>排序</td> <td>操作</td> </tr> <tr th:each="sorts : ${all}"> <td th:text="${sorts.id}">id</td> <td th:text="${sorts.space}+${sorts.sortName}">類別名稱</td> <td th:text="${sorts.orders}">排序</td> <td> <a th:href="@{'/admin/sorts/add?parentId='+ ${sorts.id}}">添加子類</a> <a th:href="@{'/admin/sorts/update?id='+ ${sorts.id}}">修改</a> <a th:href="@{'/admin/sorts/del?id='+ ${sorts.id}}" onclick="return confirm('確認(rèn)要?jiǎng)h除嗎');">刪除</a> </td> </tr> </table>
源碼下載: