基于springboot jpa thymeleaf的java無限分類的樣式及表格創(chuàng)建見:
http://www.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>源碼下載:
