無限分類是我們項目中經(jīng)常使用的功能, 這里基于ssm(Spring SpringMVC MyBatis)整合一個完善的后臺分享給大家使用
效果如下:(添加,刪除,修改,移動類別到任意目錄下等功能)
一. 創(chuàng)建表
CREATE TABLE `sorts` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `sortName` varchar(50) NOT NULL COMMENT '類別名稱', `parentId` int(11) NOT NULL DEFAULT '0' COMMENT '父級id', `sortPath` varchar(150) NOT NULL COMMENT '父級到當(dāng)前類別的所有路徑且多一個逗號(模糊搜索有用)', `levels` int(11) NOT NULL DEFAULT '1' COMMENT '層級, 默認(rèn)1, 表示第一級', `orders` int(11) NOT NULL DEFAULT '1' COMMENT '排序', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=66 DEFAULT CHARSET=utf8;
二. pojo 類
package com.pojo; public class Sorts { private int id; private String sortName; private int parentId; private String sortPath; private int levels; private int orders; private String space; //列表查詢時 前面的 間隔 public int getId() { 省略setter and getter }
三. Dao類
package com.dao; import com.pojo.Sorts; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.HashMap; @Repository("sortsDao") @Mapper public interface SortsDao { public int addSorts(Sorts sorts); //返回添加信息的主鍵 public Sorts selectBySortNameAndParendId(Sorts sorts); //查詢 當(dāng)前父類下 是否已經(jīng)有相同的類別 public Sorts selectSortsById(Integer id); public int updateSorts(Sorts sorts); public int updateSortsBySortNameOrdersId(Sorts sorts); public ArrayList<Sorts> selectByParentId(Integer id); //得到當(dāng)前類別id下的所有子類 public Sorts selectSortsByParentIdSortNameId(Sorts sorts); //查詢非當(dāng)前id下,同一個父類下是否有相同的類別 public int updateAllChildSorts(HashMap<String,Object> hm); //更新所有的修改類別的子類 public int updateAllChildSortsLevels(HashMap<String,Object> hm); //刪除當(dāng)類類別及所有的子類 public int deleteAllSortsById(Integer id); }
四. mapper文件
<?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.zhuangzi.ssm0925.dao.SortsDao"> <!-- 添加一個類別 --> <insert id="addSorts" parameterType="sorts" useGeneratedKeys="true" keyProperty="id"> insert into sorts (sortName,parentId,sortPath,levels,orders) values (#{sortName},#{parentId},#{sortPath},#{levels},#{orders}) </insert> <!-- 查詢當(dāng)前父類下是否存在相同的類別名稱--> <select id="selectBySortNameAndParendId" parameterType="sorts" resultType="sorts" > select * from sorts where parentId = #{parentId} and sortName = #{sortName} </select> <!-- 查詢當(dāng)前父類下不是原來的ID下是否存在相同的類別名稱--> <select id="selectSortsByParentIdSortNameId" parameterType="sorts" resultType="sorts" > select * from sorts where parentId = #{parentId} and sortName = #{sortName} and id <> #{id} </select> <!-- 根據(jù)ID查詢類別--> <select id="selectSortsById" parameterType="Integer" resultType="sorts" > select * from sorts where id = #{id} </select> <!-- 得到當(dāng)前類別下面所有的子類--> <select id="selectByParentId" parameterType="Integer" resultType="sorts"> select * from sorts where parentId = #{id} order by orders asc </select> <!-- 修改類別 --> <update id="updateSorts" parameterType="sorts"> update sorts set sortName = #{sortName}, parentId = #{parentId}, sortPath = #{sortPath}, levels = #{levels}, orders = #{orders} where id = #{id} </update> <!-- 父id不變, 則parentid, levels都不需要修改--> <update id="updateSortsBySortNameOrdersId" parameterType="sorts"> update sorts set sortName = #{sortName}, orders = #{orders} where id = #{id} </update> <update id="updateAllChildSorts" parameterType="Map"> update sorts set sortPath = replace(sortPath,#{oldSortPath},#{newSortPath}) where sortPath like concat('%',#{oldSortPath},'%') and id <> #{id} </update> <!-- //所有的 逗號 的個數(shù) 減一 即levels--> <update id="updateAllChildSortsLevels" parameterType="Map"> update sorts set levels = length(sortPath)- length(replace(sortPath,',','')) - 1 where sortPath like concat('%',#{newSortPath},'%') and id <> #{id} </update> <!-- 刪除當(dāng)類類別及所有的子類--> <delete id="deleteAllSortsById" parameterType="Integer"> delete from sorts where sortPath like concat ('%',',',#{id},',','%') </delete> </mapper>
五. service接口
package com.service; import com.pojo.Sorts; import java.util.ArrayList; public interface SortsService { public String addSorts(Sorts sorts); public ArrayList<Sorts> getChildren(int parentId, String space, ArrayList<Sorts> arr); public StringBuffer selectTrees(int pid,String selectName,int currentId); public Sorts selectSortsById(Integer id); public String updateSorts(Sorts sorts); public String deleteAllSortsById(Integer id); }
六. service實現(xiàn)類
package com.zhuangzi.ssm0925.service; import com.zhuangzi.ssm0925.dao.SortsDao; import com.zhuangzi.ssm0925.entity.Sorts; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; @Service("sortsService") public class SortsServiceImpl implements SortsService{ public static int initLevel = 0; @Autowired private SortsDao sortsDao; public static ArrayList<Sorts> all; //存儲所有的查詢子類數(shù)據(jù) @Override public String addSorts(Sorts sorts) { //判斷類名不能為空 if(sorts.getSortName().equals("")) { return "<script>alert('類別名稱不能為空');history.back();</script>"; } //判斷同一級下不能重復(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){ //最頂級時使用默認(rèn)設(shè)置值, 否則根據(jù)父級來決定 Sorts getSorts = sortsDao.selectSortsById(sorts.getParentId()); sorts.setLevels(getSorts.getLevels() + 1); sorts.setSortPath(getSorts.getSortPath()); //暫時為父級sortPath, 當(dāng)添加后, 再更新,將當(dāng)前的id鏈接上 } //將信息添加到數(shù)據(jù)庫sorts sortsDao.addSorts(sorts); //sorts中會更新為新增加的id主鍵 //更新sortPath 到數(shù)據(jù)庫 sorts.setSortPath(sorts.getSortPath() + sorts.getId() + ","); sortsDao.updateSorts(sorts);// return "<script>alert('添加成功');location.href='/admin/sorts/list';</script>"; } //parentId: 父類 ID, 查詢當(dāng)前類別下的所有子類 //space : // 類別前面的空隔 @Override public ArrayList<Sorts> getChildren(int parentId, String space, ArrayList<Sorts> arr){ if(arr == null){ //第一次查詢 System.out.println(parentId); arr = sortsDao.selectByParentId(parentId); initLevel = arr.get(0).getLevels(); all = new ArrayList<>(); //第一次時, 初始化, 避免刷新調(diào)用重新添加信息 } if(arr != null){ for(Sorts sorts : arr){ //根據(jù)級別不一樣, 在前面加上相應(yīng)的分隔符 int levels = sorts.getLevels(); if(levels == initLevel){ sorts.setSpace(""); } else if(levels == initLevel + 1){ space = " |---->"; sorts.setSpace(space); } else{ sorts.setSpace(space); } all.add(sorts); //將所有的信息都加到all里, 并增加一個space字段 parentId = sorts.getId(); ArrayList<Sorts> arr_child = sortsDao.selectByParentId(parentId); if(arr_child != null){ getChildren(parentId," |" + space,arr_child); } } } return all; } //得到無限分類的select下拉列表 //pid : 父id //selectName select的名字 //currenId : 被選擇的id, 沒有的話,傳遞0 @Override public StringBuffer selectTrees(int pid,int currentId){ StringBuffer sBuffer = new StringBuffer(); ArrayList<Sorts> results = getChildren(pid,"",null); if(results != null){ 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"); } } } return sBuffer; } @Override public Sorts selectSortsById(Integer id) { return sortsDao.selectSortsById(id); } @Override public String updateSorts(Sorts sorts) { //判斷類名不能為空 if(sorts.getSortName().equals("")) { return "<script>alert('類別名稱不能為空');history.back();</script>"; } //根據(jù)id得到原來的信息 Sorts oldSorts = sortsDao.selectSortsById(sorts.getId()); int oldPid = oldSorts.getParentId(); //原父id String oldSortPath = oldSorts.getSortPath(); //判斷類別名稱是否重復(fù) Sorts exitSorts = sortsDao.selectSortsByParentIdSortNameId(sorts); if(exitSorts != null){ return "<script>alert('類別已經(jīng)存在,請更換類別名稱');history.back();</script>"; } if(oldPid == sorts.getParentId()){ //父id不變, 則parentid, level都不需要修改 sortsDao.updateSortsBySortNameOrdersId(sorts); } else if(sorts.getParentId() == 0){ //移動到一級類別 sorts.setSortPath("0," + sorts.getId() + ","); sorts.setLevels(1); //更新當(dāng)前類別信息 sortsDao.updateSorts(sorts); //更新所有的修改類別的子類sortPath HashMap<String,Object> hm = new HashMap<>(); hm.put("oldSortPath",oldSortPath); hm.put("newSortPath",sorts.getSortPath()); hm.put("id",sorts.getId()); sortsDao.updateAllChildSorts(hm); //更新所有子類的層級 sortsDao.updateAllChildSortsLevels(hm); } else{ //判斷是否移到到了子類另, 這樣是不允許的, 中間會斷層 //得到當(dāng)前父類的path Sorts parentSorts = sortsDao.selectSortsById(sorts.getParentId()); String parentSortPath = parentSorts.getSortPath(); if(parentSortPath.indexOf(oldSortPath) >= 0){ return "<script>alert('類別不能選擇為原父類的子類');history.back();</script>"; } else{ //父類更新到上一級或者其它的類別下, 那么該類別下所有的子類都需要更新父級sortpath //新的sortpath String newSortPath = parentSortPath + sorts.getId() + ","; int newLevel = parentSorts.getLevels() + 1; sorts.setSortPath(newSortPath); sorts.setLevels(newLevel); sortsDao.updateSorts(sorts); //更新所有的修改類別的子類 //更新所有的修改類別的子類sortPath HashMap<String,Object> hm = new HashMap<>(); hm.put("oldSortPath",oldSortPath); hm.put("newSortPath",sorts.getSortPath()); hm.put("id",sorts.getId()); sortsDao.updateAllChildSorts(hm); //更新所有子類的層級 sortsDao.updateAllChildSortsLevels(hm); } } 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>"; } }
七. 類別控制器
package controller; import pojo.Sorts; import service.SortsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; @Controller public class SortsController { @Autowired @Qualifier("sortsService") private SortsService sortsService; @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") public void addSave(Sorts sorts, HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println(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 = sortsService.selectSortsById(id); model.addAttribute("sorts",sorts); model.addAttribute("selectTrees",sortsService.selectTrees(0,"parentId",sorts.getParentId())); return "admin/sorts/update"; } @PostMapping(value = "/admin/sorts/updateSave") public void updateSave(Sorts sorts, HttpServletResponse response) throws IOException{ response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println(sortsService.updateSorts(sorts)); } @GetMapping(value = "/admin/sorts/del") public void del(@RequestParam(defaultValue = "0") Integer id, HttpServletResponse response) throws IOException{ response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println(sortsService.deleteAllSortsById(id)); } }
八. 控制器調(diào)用類
package com.controller; import com.pojo.Student; import com.service.SortsService; import com.service.StudentService; import com.service.StudentServiceImpl; import javafx.scene.chart.ValueAxis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.io.IOException; import java.util.ArrayList; @Controller public class StudentController { @Autowired @Qualifier("sortsService") private SortsService sortsService; @Autowired @Qualifier("studentService") private StudentService studentService; @GetMapping(value = "/admin/studentAdd") public String studentAdd(Model model){ model.addAttribute("blood", sortsService.selectTrees(61,"blood",62)); return "admin/student/add"; } @PostMapping(value = "/admin/studentAddSave") @ResponseBody public int studentAddSave(Student student) throws IOException { return studentService.addStudent(student); } //顯示學(xué)生信息 @GetMapping(value = "/admin/studentList") public String studentList(Student student, Model model){ ArrayList list = studentService.studentList(student); model.addAttribute("list",list); return "admin/student/list"; } }
九. 其它類調(diào)用下拉信息
@GetMapping(value = "/admin/studentAdd") public String studentAdd(Model model){ model.addAttribute("blood", sortsService.selectTrees(61,62)); return "admin/student/add"; }
JSP頁面:
顯示調(diào)用效果:
請把相應(yīng)的dao, service, controller, mapper及視圖html文件放到自己的相應(yīng)
基于Thymeleaf