1. 程式人生 > >基於zTree的Jsp通用動態級聯樹結構

基於zTree的Jsp通用動態級聯樹結構

spring mon body model execution lba common req 定義數據

1、categoryTree.html 通用頁面

<link rel="stylesheet" href="/static/plugins/zTree_v3/css/zTreeStyle.css" type="text/css">
<style>
    /*展示樹狀結構的樣式*/
    ul.ztree {position:relative;top: 32px;left:0px;z-index:999;border: 1px solid #617775;background: #f0f7fb;width:220px;height:360px;overflow-y:scroll;overflow-x:auto;display: none}
</style>
<script type="text/javascript" src="/static/plugins/zTree_v3/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="/static/plugins/zTree_v3/js/jquery.ztree.core.js"></script>
<SCRIPT type="text/javascript" >
    var node_id ,node_name;
    var zTreeObj,
        setting = {
            view: {
                selectedMulti: false //多選選項
            },
            data:{//定義數據規範
                simpleData:{
                    enable:false,//是否使用簡單的數據結構,本例使用標準json樹狀結構
                    idKey:'cat_id',//nodeId字段名稱
                    pIdKey:'parent_id',//parentId字段名稱
                    rootPId:0 //跟nodeId的值
                },
                key:{ //字段名稱定義
                    name:"cat_name",//展示名稱
                    children:"nodes"//子節點對象
                }
            }
        },
        zTreeNodes = [];
        //加載動態數據
        function loadTree(data){
            if(data && data.length>0){
                zTreeNodes = data;
                zTreeObj = $.fn.zTree.init($("#tree"), setting, zTreeNodes);
            }

        }
    $(document).ready(function(){
        $.post("/category/getCategoryTree",null,loadTree);
    });
</SCRIPT>
<ul id="tree" class="ztree"></ul>

2、調用方法

<div class="t_text ml10" id="category">
   <c:import url="../common/categoryTree.jsp"/> <!--如果是靜態頁面可以使用jquery.load() 方法 -->
   <input type="hidden" name="cat_id" id="cat_id" value="${pageParam.cat_id }" />
   <input placeholder="類別" type="text" name="cat_name" id="cat_name" />
</div>

3.controller

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * @author  liujun
 * @since 2018/1/18.
 * 產品分類
 */
@Controller
@RequestMapping("/category")
public class CategoryController {
    Logger logger = LoggerFactory.getLogger(CategoryController.class);
    @Autowired
    CategoryTreeService categoryService;
    @RequestMapping(value = "/getCategoryTree")
    @ResponseBody
    public List<CategoryTree> getCategoryTree(){
        logger.info("處理請求:/category/getCategoryTree");
        return this.categoryService.getCategoryTree();
    }
}

4、service接口

import java.util.List;


/**
 * @author  liujun
 * @since 2018/1/18.
 * 產品類別服務接口
 */
public interface CategoryTreeService extends CommonService<CategoryTree,Long>{
    /**
     * 獲取類別樹
     * @return List<CategoryTree>商品類別{@link CategoryTree}
     */
    public List<CategoryTree> getCategoryTree();
}

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * Created by liujun on 2018/1/22.
 */
public interface CommonService <E,ID extends Serializable> {
    public E get(ID id);
    public E find(ID id);
    public List<E> getAll();
    public Long getTotalCount();
    public E save(E entity);
    public E update(E entity);
    public void delete(E entity);
    public void delete(ID id);
    public void delete(Collection<E> entities);
    public void flush();
    public List<E> findAll(Specification<E> spec);
    public Page<E> findAll(Pageable pageable);
    public Page<E> findAll(Specification<E> spec, Pageable pageable);
    public List<E> findAll(Specification<E> spec, Sort sort);
    public long count(Specification<E> spec);
}

5、service實現

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author liujun
 * @since 2018/1/18.
 * @see CategoryTreeServiceImpl
 * 產品類別業務類{@link Service}
 */
@Service
public class CategoryTreeServiceImpl extends CommonServiceImpl<CategoryTree,Long> implements CategoryTreeService {
    @Resource(name = "baseSqlDaoImpl")
    CustomBaseSqlDao baseSqlDao;
    @Autowired
    CategoryTreeDao categoryTreeDao;
    @Override
    public List<CategoryTree> getCategoryTree() {
        String hql = " select o from CategoryTree o where o.parent_id = 0 order by o.sort_order";
        return this.baseSqlDao.queryForList(hql);
    }
    @Autowired
    public void setCategoryDao(CategoryTreeDao categoryTreeDao) {
        super.setCommonDao(categoryTreeDao);
        this.categoryTreeDao = categoryTreeDao;
    }
}

/**
 * 基礎Service的定義
 * @author Jeff Xu
 * @since 2015-12-09
 * @param <E>
 * @param <ID>
 */
public abstract class CommonServiceImpl<E,ID extends Serializable>  implements CommonService <E,ID> {

   protected CommonDao<E,ID> commonDao;

   public void setCommonDao(CommonDao<E, ID> commonDao) {
      this.commonDao = commonDao;
   }

   public CommonDao<E, ID> getCommonDao() {
      return commonDao;
   }
   
   /**
    * 根據ID獲取某個Entity
    * @param id
    * @return
    */
   public E get(ID id) {
      return commonDao.getOne(id);
   }

   /**
    * 根據ID查找某個Entity(建議使用)
    * @param id
    * @return
    */
   public E find(ID id) {
      return commonDao.findOne(id);
   }

   /**
    * 獲取所有的Entity列表
    * @return
    */
   public List<E> getAll() {
      return commonDao.findAll();
   }
   
   /**
    * 獲取Entity的總數
    * @return
    */
   public Long getTotalCount() {
      return commonDao.count();
   }

   /**
    * 保存Entity
    * @param entity
    * @return
    */
   public E save(E entity) {
      return commonDao.save(entity);
   }

   /**
    * 修改Entity
    * @param entity
    * @return
    */
   public E update(E entity) {
      return commonDao.save(entity);
   }
   
   /**
    * 刪除Entity
    * @param entity
    */
   public void delete(E entity) {
      commonDao.delete(entity);
   }

   /**
    * 根據Id刪除某個Entity
    * @param id
    */
   public void delete(ID id) {
      commonDao.delete(id);
   }

   /**
    * 刪除Entity的集合類
    * @param entities
    */
   public void delete(Collection<E> entities) {
      commonDao.delete(entities);
   }

   /**
    * 清空緩存,提交持久化
    */
   public void flush() {
      commonDao.flush();
   }
   
   /**
    * 根據查詢信息獲取某個Entity的列表
    * @param spec
    * @return
    */
   public List<E> findAll(Specification<E> spec) {
      return commonDao.findAll(spec);
   }
   
   /**
    * 獲取Entity的分頁信息
    * @param pageable
    * @return
    */
   public Page<E> findAll(Pageable pageable){
      return commonDao.findAll(pageable);
   }
   
   /**
    * 根據查詢條件和分頁信息獲取某個結果的分頁信息
    * @param spec
    * @param pageable
    * @return
    */
   public Page<E> findAll(Specification<E> spec, Pageable pageable) {
      return commonDao.findAll(spec, pageable);
   }
   
   /**
    * 根據查詢條件和排序條件獲取某個結果集列表
    * @param spec
    * @param sort
    * @return
    */
   public List<E> findAll(Specification<E> spec, Sort sort) {
      return commonDao.findAll(spec);
   }
   
   /**
    * 查詢某個條件的結果數集
    * @param spec
    * @return
    */
   public long count(Specification<E> spec) {
      return commonDao.count(spec);
   }


}

6、dao接口

/**
 * Created by liujun on 2018/1/22.
 */
public interface CustomBaseSqlDao {
    public List<Map<String, Object>> querySqlObjects(String sql, Integer currentPage, Integer rowsInPage);
    public List<Map<String, Object>> querySqlObjects(String sql);
    public List<Map<String, Object>> querySqlObjects(String sql, List<Object> params);
    public List<Map<String, Object>> querySqlObjects(String sql, Object params, Integer currentPage,Integer rowsInPage);
    public PageModel<Map<String, Object>> querySqlObjects(String sql, String sbCount, Map<String, Object> params, Integer currentPage, Integer rowsInPage);
    public int getCount(String sql);
    public List queryForList(String hql, List<Object> params);
    public List queryByMapParams(String hql, Map<String, Object> params, Integer currentPage,Integer pageSize);
    public List queryByMapParams(String hql, Map<String, Object> params);
    public List queryForList(String hql);
    public PageModel queryForPage(String hql,int currentPage,int pageSize);
    public PageModel queryForPageWithParams(String hql, String hqlCount, Map<String,Object> params, int currentPage,int pageSize);
    public PageModel queryForPageWithParams(String hql,Map<String,Object> params, int currentPage,int pageSize);
    public PageModel queryForPageBySql(String sql,Integer currentPage,Integer pageSize);
    public PageModel queryForPageBySql(String sql,Map<String,Object> params,Integer currentPage,Integer pageSize);
    public Long queryCount(String hql, Map<String, Object> params);
    public Integer queryCountBySql(String sql, Map<String, Object> params);
    public int executeSql(String sql, List<Object> params);
}
/**
 * Created by liujun on 2018/1/19.
 */
public interface CategoryTreeDao extends CommonDao<CategoryTree,Long>{
}

/**
 * 基礎Dao接口定義
 * @since 2015-12-09
 */
@NoRepositoryBean
public interface CommonDao<E,ID extends Serializable>  extends JpaRepository<E,ID>, JpaSpecificationExecutor<E> {

}

7、dao實現

@Component(value="baseSqlDaoImpl")
public class CustomBaseSqlDaoImpl implements CustomBaseSqlDao {
   
   @Autowired
   private EntityManager em;
   
   public List<Map<String, Object>> querySqlObjects(String sql, Integer currentPage,Integer rowsInPage){
      return this.querySqlObjects(sql, null, currentPage, rowsInPage);
   }
   
   public List<Map<String, Object>> querySqlObjects(String sql){
      return this.querySqlObjects(sql, null, null, null);
   }
   
   public List<Map<String, Object>> querySqlObjects(String sql, List<Object> params){
      return this.querySqlObjects(sql, params, null, null);
   }
   
   @SuppressWarnings("unchecked")
   public List<Map<String, Object>> querySqlObjects(String sql, Object params, Integer currentPage,Integer rowsInPage){
      Query qry = em.createNativeQuery(sql);
      SQLQuery s = qry.unwrap(SQLQuery.class);
      
      //設置參數
      if(params != null){
         if(params instanceof List){
            List<Object> paramList = (List<Object>) params;
            for(int i = 0, size = paramList.size(); i < size; i++){
               qry.setParameter(i+1, paramList.get(i));
            }
         }else if(params instanceof Map){
            Map<String, Object> paramMap = (Map<String, Object>) params;
            for(String key : paramMap.keySet()){
               qry.setParameter(key, paramMap.get(key));
            }
         }
      }
      
      if (currentPage != null && rowsInPage != null) {//判斷是否有分頁
         // 起始對象位置
         qry.setFirstResult(rowsInPage * (currentPage - 1));
         // 查詢對象個數
         qry.setMaxResults(rowsInPage);
      }
      s.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
      List<Map<String, Object>> resultList=new ArrayList<Map<String, Object>>();
      try {
         resultList=s.list();
      } catch (Exception e) {
      }finally{
         em.close();
      }
      return resultList;
   }
   
   public PageModel<Map<String, Object>> querySqlObjects(String sql,
         String sbCount, Map<String, Object> params, Integer currentPage,Integer rowsInPage){
      PageModel<Map<String, Object>> pageModel = new PageModel<Map<String, Object>>();
      
      List<Map<String, Object>> list = this.querySqlObjects(sql, params, currentPage, rowsInPage);

      pageModel.setList(list);
      
      if(currentPage == null || rowsInPage == null){
         pageModel.setTotalCount(list == null ? 0 : list.size());
      }else{
         Integer count = this.queryCountBySql(sbCount, params);
         
         pageModel.setCurrentPage(currentPage);
         pageModel.setTotalCount(count);
         pageModel.setPageSize(rowsInPage);
         
         int totalPage = 0;
         if(count%rowsInPage == 0){
            totalPage = count / rowsInPage;
         }else{
            totalPage = count / rowsInPage + 1;
         }
         
         pageModel.setTotalPage(totalPage);
      }
      
      
      return pageModel;
   }
   
   
   public int getCount(String sql){
      String sqlCount="select count(0) count_num from ("+sql+") as total";
      List<Map<String, Object>> list = this.querySqlObjects(sqlCount);
      if(list.size() > 0){
         int countNum=((BigInteger) list.get(0).get("count_num")).intValue();
         return countNum;
      }else{
         return 0;
      }
   }
   
   /**
    * 處理sql語句
    * 
    * @param _strSql
    * @return
    */
   public String toSql(String _strSql) {
      String strNewSql = _strSql;

      if (strNewSql != null) {
         strNewSql = regReplace("'", "''", strNewSql);
      } else {
         strNewSql = "";
      }

      return strNewSql;
   }

   private String regReplace(String strFind, String strReplacement, String strOld) {
      String strNew = strOld;
      Pattern p = null;
      Matcher m = null;
      try {
         p = Pattern.compile(strFind);
         m = p.matcher(strOld);
         strNew = m.replaceAll(strReplacement);
      } catch (Exception e) {
      }

      return strNew;
   }
   
   /**
    * 根據hql語句查詢數據
    * @param hql
    * @return
    */
   @SuppressWarnings("rawtypes")
   public List queryForList(String hql, List<Object> params){
      Query query = em.createQuery(hql);
      List list = null;
      try {
         if(params != null && !params.isEmpty()){
            for(int i=0,size=params.size();i<size;i++){
               query.setParameter(i+1, params.get(i));
            }
         }
         list = query.getResultList();
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }
      return list;
   }
   
   @SuppressWarnings("rawtypes")
   public List queryByMapParams(String hql, Map<String, Object> params, Integer currentPage,Integer pageSize){
      //EntityManager em = this.emf.createEntityManager();
      Query query = em.createQuery(hql);
      List list = null;
      try {
         if(params != null && !params.isEmpty()){
            for(Map.Entry<String,Object> entry: params.entrySet()){
               query.setParameter(entry.getKey(), entry.getValue());
            }
         }
         
         if(currentPage != null && pageSize != null){
            query.setFirstResult((currentPage-1)*pageSize);
            query.setMaxResults(pageSize);
         }
         list = query.getResultList();
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }
      
      return list;
   }
   
   @SuppressWarnings("rawtypes")
   public List queryByMapParams(String hql, Map<String, Object> params){
      return queryByMapParams(hql, params, null, null);
   }
   
   @SuppressWarnings("rawtypes")
   public List queryForList(String hql){
      return queryForList(hql, null);
   }
   
   /**
    * 根據hql語句和分頁條件查找分頁數據
    * @param hql
    * @param currentPage
    * @param pageSize
    * @return
    */
   @SuppressWarnings({ "rawtypes", "unchecked" })
   public PageModel queryForPage(String hql,int currentPage,int pageSize){
      PageModel page = new PageModel();
      List list = null;
      Integer totalCount = 0;
      Integer totalPage = 0; //總頁數
      try {
         int firstResult = (currentPage-1)*pageSize;
         Query query = em.createQuery(hql);
         query.setMaxResults(pageSize);
         query.setFirstResult(firstResult);
         list = query.getResultList();
         
         Query query2 = em.createQuery(hql);
         List list2 = query2.getResultList();
         totalCount = (list2 == null) ? 0 : list2.size();
         if(totalCount % pageSize == 0){
            totalPage = totalCount/pageSize;
         }else{
            totalPage = totalCount/pageSize + 1;
         }
         
         page.setCurrentPage(currentPage);
         page.setList(list);
         page.setPageSize(pageSize);
         page.setTotalCount(totalCount);
         page.setTotalPage(totalPage);
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }     
      return page;
   }
   
   /**
    * 
    * @param hql
    * @param hqlCount  查詢所有數據的hql
    * @param params
    * @param currentPage
    * @param pageSize
    * @return
    */
   @SuppressWarnings({ "unchecked", "rawtypes" })
   public PageModel queryForPageWithParams(String hql, String hqlCount, Map<String,Object> params, int currentPage,int pageSize){
      PageModel page = new PageModel();
      List<Object> list = null;
      Integer totalCount = 0;
      Integer totalPage = 0;
      
      //EntityManager em = this.emf.createEntityManager();
      Query query = em.createQuery(hql);
      
      try {
         
         if(params != null){
            for(Map.Entry<String,Object> entry: params.entrySet()){
               query.setParameter(entry.getKey(), entry.getValue());
            }
         }
         
         query.setMaxResults(pageSize);
         query.setFirstResult((currentPage-1)*pageSize);
         list = query.getResultList();
         
         
         totalCount = this.queryCount(hqlCount, params).intValue();
         if(totalCount % pageSize == 0){
            totalPage = totalCount/pageSize;
         }else{
            totalPage = totalCount/pageSize + 1;
         }
         
         page.setCurrentPage(currentPage);
         page.setPageSize(pageSize);
         page.setList(list);
         page.setTotalCount(totalCount);
         page.setTotalPage(totalPage);
         
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }        
      return page;
   }
   
   @SuppressWarnings({ "unchecked", "rawtypes" })
   public PageModel queryForPageWithParams(String hql,Map<String,Object> params, int currentPage,int pageSize){
      PageModel page = new PageModel();
      List<Object> list = null;
      Integer totalCount = 0;
      Integer totalPage = 0;
      
      //EntityManager em = this.emf.createEntityManager();
      Query query = em.createQuery(hql);
      
      try {
         
         if(params != null){
            for(Map.Entry<String,Object> entry: params.entrySet()){
               query.setParameter(entry.getKey(), entry.getValue());
            }
         }
         
         query.setMaxResults(pageSize);
         query.setFirstResult((currentPage-1)*pageSize);
         list = query.getResultList();
         
         Query queryTotal = em.createQuery(hql);
         
         if(params != null){
            for(Map.Entry<String,Object> entry: params.entrySet()){
               queryTotal.setParameter(entry.getKey(), entry.getValue());
            }
         }
         
         List<Object> totlaList = queryTotal.getResultList(); 
         totalCount = (totlaList == null) ? 0 : totlaList.size();
         if(totalCount % pageSize == 0){
            totalPage = totalCount/pageSize;
         }else{
            totalPage = totalCount/pageSize + 1;
         }
         
         page.setCurrentPage(currentPage);
         page.setPageSize(pageSize);
         page.setList(list);
         page.setTotalCount(totalCount);
         page.setTotalPage(totalPage);
         
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }        
      return page;
   }

        /**
    * 根據SQL語句查詢分頁
    * @param sql
    * @param currentPage
    * @param pageSize
    * @return
    */
   @SuppressWarnings({ "rawtypes", "unchecked" })
   public PageModel queryForPageBySql(String sql,Integer currentPage,Integer pageSize){
      PageModel page = new PageModel();
      Integer totalCount = 0;
      Integer totalPage = 0;
      
      //EntityManager em = this.emf.createEntityManager();
      Query qry = em.createNativeQuery(sql);
      Query qry2 = em.createNativeQuery(sql);
      SQLQuery s = qry.unwrap(SQLQuery.class);
      if (currentPage != null && pageSize != null) {//判斷是否有分頁
         // 起始對象位置
         qry.setFirstResult(pageSize * (currentPage - 1));
         // 查詢對象個數
         qry.setMaxResults(pageSize);
      }
      s.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
      List<Map> resultList=new ArrayList<Map>();
      List list = qry2.getResultList();
      totalCount = (list == null ? 0 : list.size());
      if(totalCount % pageSize == 0){
         totalPage = totalCount/pageSize;
      }else{
         totalPage = totalCount/pageSize + 1;
      }
      try {
         resultList=s.list();
         page.setCurrentPage(currentPage);
         page.setPageSize(pageSize);
         page.setList(resultList);
         page.setTotalCount(totalCount);
         page.setTotalPage(totalPage);
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }     
      return page;
   }
   
   @SuppressWarnings({ "rawtypes", "unchecked" })
   public PageModel queryForPageBySql(String sql,Map<String,Object> params,Integer currentPage,Integer pageSize){
      PageModel page = new PageModel();
      Integer totalCount = 0;
      Integer totalPage = 0;
      
      Query qry = em.createNativeQuery(sql);
      Query qry2 = em.createNativeQuery(sql);
      
      for(Map.Entry<String,Object> entry: params.entrySet()){
         qry.setParameter(entry.getKey(), entry.getValue());
         qry2.setParameter(entry.getKey(), entry.getValue());
      }
      
      SQLQuery s = qry.unwrap(SQLQuery.class);
      if (currentPage != null && pageSize != null) {//判斷是否有分頁
         // 起始對象位置
         qry.setFirstResult(pageSize * (currentPage - 1));
         // 查詢對象個數
         qry.setMaxResults(pageSize);
      }
      s.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
      List<Map> resultList=new ArrayList<Map>();
      List list = qry2.getResultList();
      totalCount = (list == null ? 0 : list.size());
      if(totalCount % pageSize == 0){
         totalPage = totalCount/pageSize;
      }else{
         totalPage = totalCount/pageSize + 1;
      }
      try {
         resultList=s.list();
         page.setCurrentPage(currentPage);
         page.setPageSize(pageSize);
         page.setList(resultList);
         page.setTotalCount(totalCount);
         page.setTotalPage(totalPage);
      } catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }     
      return page;
   }
   
   /**
    * 查詢總數
    * @param hql
    * @param params
    * @return
    */
   public Long queryCount(String hql, Map<String, Object> params){
      //EntityManager em = this.emf.createEntityManager();
      Query query = em.createQuery(hql);
      Long count = null;
      try{
         if(params != null && !params.isEmpty()){
            for(Map.Entry<String,Object> entry: params.entrySet()){
               query.setParameter(entry.getKey(), entry.getValue());
            }
         }
         count = (Long) query.getSingleResult();
      }catch (Exception e) {
         e.printStackTrace();
      }finally{
         em.close();
      }
      
      return count;
   }
   
   /**
    * 查詢總數
    * @param hql
    * @param params
    * @return
    */
   public Integer queryCountBySql(String sql, Map<String, Object> params){
      Integer count = null;
      try {
         Query query = em.createNativeQuery(sql);
         if(params != null && !params.isEmpty()){
            for(Map.Entry<String,Object> entry: params.entrySet()){
               query.setParameter(entry.getKey(), entry.getValue());
            }
         }
         
         Object obj = query.getSingleResult();
         if(obj instanceof BigInteger){
            count = ((BigInteger) obj).intValue();
         }else{
            count = (Integer) obj;
         }
          
      } finally {
         if(em != null){
            em.close();
         }
      }
      return count;
   }
   
   /**
    * select count(*) from table 
    * @param sql
    * @param params
    * @return
    */
   public int executeSql(String sql, List<Object> params){
      try {
         Query query = em.createNativeQuery(sql);
         if(params != null && !params.isEmpty()){
            for(int i = 0, size = params.size(); i < size; i++){
               query.setParameter(i+1, params.get(i));
            }
         }
         return query.executeUpdate();
      } finally {
         if(em != null){
            em.close();
         }
      }
   }
   

}

8、entity

/**
 * Created by liujun on 2018/1/18.
 */
@Entity
@Table(name="ecs_category")
public class CategoryTree implements Serializable{
    private Long cat_id;//id主鍵
    private String cat_name; //名稱
    private Long parent_id;//父
    private String keywords;//關鍵字
    private String cat_desc;//描述
    private Long sort_order;//排序
    private String measure_unit;//單位
    private Integer show_in_nav;//
    private String style;
    private Integer is_show;//是否顯示
    private Integer grade;//級別
    private String filter_attr;
    private Long category_index;
    private Long show_in_index;
//    private String path_name;
    private Integer is_virtual;
    private Long show_goods_num;
//    CategoryTree partent = new CategoryTree();//父
    List<CategoryTree> nodes = new ArrayList<CategoryTree>();//子
    @Id
   @Column(name="cat_id", length = 8, nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getCat_id() {
        return cat_id;
    }

    public void setCat_id(Long cat_id) {
        this.cat_id = cat_id;
    }
   @Column(name="cat_name")
    public String getCat_name() {
        return cat_name;
    }

    public void setCat_name(String cat_name) {
        this.cat_name = cat_name;
    }
    @Column(name="parent_id")
    public Long getParent_id() {
        return parent_id;
    }

    public void setParent_id(Long parent_id) {
        this.parent_id = parent_id;
    }

    @Column(name="keywords")
    public String getKeywords() {
        return keywords;
    }

    public void setKeywords(String keywords) {
        this.keywords = keywords;
    }
   @Column(name="cat_desc")
    public String getCat_desc() {
        return cat_desc;
    }

    public void setCat_desc(String cat_desc) {
        this.cat_desc = cat_desc;
    }

   @Column(name="sort_order")
    public Long getSort_order() {
        return sort_order;
    }

    public void setSort_order(Long sort_order) {
        this.sort_order = sort_order;
    }
   @Column(name="measure_unit")
    public String getMeasure_unit() {
        return measure_unit;
    }

    public void setMeasure_unit(String measure_unit) {
        this.measure_unit = measure_unit;
    }
   @Column(name="show_in_nav")
    public Integer getShow_in_nav() {
        return show_in_nav;
    }

    public void setShow_in_nav(Integer show_in_nav) {
        this.show_in_nav = show_in_nav;
    }
   @Column(name="style")
    public String getStyle() {
        return style;
    }

    public void setStyle(String style) {
        this.style = style;
    }
   @Column(name="is_show")
    public Integer getIs_show() {
        return is_show;
    }

    public void setIs_show(Integer is_show) {
        this.is_show = is_show;
    }
   @Column(name="grade")
    public Integer getGrade() {
        return grade;
    }

    public void setGrade(Integer grade) {
        this.grade = grade;
    }
   @Column(name="filter_attr")
    public String getFilter_attr() {
        return filter_attr;
    }

    public void setFilter_attr(String filter_attr) {
        this.filter_attr = filter_attr;
    }
   @Column(name="category_index")
    public Long getCategory_index() {
        return category_index;
    }

    public void setCategory_index(Long category_index) {
        this.category_index = category_index;
    }

   @Column(name="show_in_index")
    public Long getShow_in_index() {
        return show_in_index;
    }

    public void setShow_in_index(Long show_in_index) {
        this.show_in_index = show_in_index;
    }
// @Column(name="path_name")
//    public String getPath_name() {
//        return path_name;
//    }
//
//    public void setPath_name(String path_name) {
//        this.path_name = path_name;
//    }
   @Column(name="is_virtual")
    public Integer getIs_virtual() {
        return is_virtual;
    }

    public void setIs_virtual(Integer is_virtual) {
        this.is_virtual = is_virtual;
    }
   @Column(name="show_goods_num")
    public Long getShow_goods_num() {
        return show_goods_num;
    }

    public void setShow_goods_num(Long show_goods_num) {
        this.show_goods_num = show_goods_num;
    }
    @OneToMany(cascade = CascadeType.REFRESH,fetch = FetchType.LAZY)
    @JoinColumn(name="parent_id")
    @Where(clause = "is_virtual=0")
    @OrderBy(value = "sort_order asc")
    public List<CategoryTree> getNodes() {
        return nodes;
    }

    public void setNodes(List<CategoryTree> nodes) {
        this.nodes = nodes;
    }
}

9、配置

<!-- Jpa Entity Manager 配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
   <property name="dataSource" ref="druidDataSource"/>
   <property name="persistenceProvider">
      <bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
   </property>
   <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
   <property name="packagesToScan">
      <list>
         <value>com.jeff.tianti</value>
         <value>com.youlin</value>
      </list>
   </property>
   <property name="jpaProperties">
      <props>
         <!-- 命名規則 My_NAME->MyName -->
         <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
      </props>
   </property>
</bean>

<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
   <property name="databasePlatform">
      <bean factory-method="getDialect" class="org.springside.modules.persistence.Hibernates">
         <constructor-arg ref="druidDataSource"/>
      </bean>
   </property>
   
   <property name="generateDdl" value="true" />
   <property name="showSql" value="true" />
   <!--  
   <property name="jpaPropertyMap">
      <map>
         <entry key="hibernate.query.substitutions" value="true 1, false 0" />
         <entry key="hibernate.default_batch_fetch_size" value="16" />
         <entry key="hibernate.max_fetch_depth" value="2" />
         <entry key="hibernate.generate_statistics" value="true" />
         <entry key="hibernate.bytecode.use_reflection_optimizer" value="true" />
         <entry key="hibernate.cache.use_second_level_cache" value="false" />
         <entry key="hibernate.cache.use_query_cache" value="false" />
      </map>
   </property>
   -->
</bean>

<!-- Spring Data Jpa配置 -->
   <jpa:repositories base-package="com.yours"  transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>
  
<!-- Jpa 事務配置 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<!-- 事務聲明配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
   <tx:attributes>
      <tx:method name="save*" propagation="REQUIRED" />
      <tx:method name="create*" propagation="REQUIRED" />
      <tx:method name="remove*" propagation="REQUIRED" />
      <tx:method name="del*" propagation="REQUIRED" />
      <tx:method name="update*" propagation="REQUIRED" />
      <tx:method name="modify*" propagation="REQUIRED" />
      <tx:method name="get*" propagation="REQUIRED" />
      <tx:method name="find*" propagation="REQUIRED" />
      <tx:method name="do*" propagation="REQUIRED" />
      <tx:method name="*" propagation="REQUIRED" read-only="true"/>
   </tx:attributes>
</tx:advice>
<aop:config>
   <aop:pointcut expression="execution (* com..service..*.*(..))" id="txPointcut" />
   <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>

10、效果圖

技術分享圖片

11、dom結構

<ul id="tree" class="ztree"><li id="tree_1" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_1_switch" title="" class="button level0 switch roots_close" treenode_switch=""></span><a id="tree_1_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="家用電器"><span id="tree_1_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_1_span" class="node_name">家用電器</span></a></li><li id="tree_45" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_45_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_45_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="手機、數碼、通信"><span id="tree_45_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_45_span" class="node_name">手機、數碼、通信</span></a></li><li id="tree_80" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_80_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_80_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="電腦、辦公"><span id="tree_80_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_80_span" class="node_name">電腦、辦公</span></a><ul id="tree_80_ul" class="level0 line" style="display: none;"><li id="tree_81" class="level1" tabindex="0" hidefocus="true" treenode=""><span id="tree_81_switch" title="" class="button level1 switch center_docu" treenode_switch=""></span><a id="tree_81_a" class="level1" treenode_a="" onclick="" target="_blank" style="" title="筆記本"><span id="tree_81_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_81_span" class="node_name">筆記本</span></a></li><li id="tree_82" class="level1" tabindex="0" hidefocus="true" treenode=""><span id="tree_82_switch" title="" class="button level1 switch bottom_docu" treenode_switch=""></span><a id="tree_82_a" class="level1" treenode_a="" onclick="" target="_blank" style="" title="辦工桌"><span id="tree_82_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_82_span" class="node_name">辦工桌</span></a></li></ul></li><li id="tree_83" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_83_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_83_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="家居、家具、家裝、廚具"><span id="tree_83_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_83_span" class="node_name">家居、家具、家裝、廚具</span></a></li><li id="tree_134" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_134_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_134_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="男裝、女裝、內衣、珠寶"><span id="tree_134_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_134_span" class="node_name">男裝、女裝、內衣、珠寶</span></a></li><li id="tree_189" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_189_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_189_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="個護化妝、清潔用品"><span id="tree_189_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_189_span" class="node_name">個護化妝、清潔用品</span></a></li><li id="tree_225" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_225_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_225_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="酒類飲料"><span id="tree_225_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_225_span" class="node_name">酒類飲料</span></a></li><li id="tree_260" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_260_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_260_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="鞋靴、箱包、鐘表、奢侈品"><span id="tree_260_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_260_span" class="node_name">鞋靴、箱包、鐘表、奢侈品</span></a></li><li id="tree_261" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_261_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_261_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="運動戶外"><span id="tree_261_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_261_span" class="node_name">運動戶外</span></a></li><li id="tree_262" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_262_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_262_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="汽車、汽車用品"><span id="tree_262_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_262_span" class="node_name">汽車、汽車用品</span></a></li><li id="tree_263" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_263_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_263_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="母嬰、玩具樂器"><span id="tree_263_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_263_span" class="node_name">母嬰、玩具樂器</span></a></li><li id="tree_314" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_314_switch" title="" class="button level0 switch center_close" treenode_switch=""></span><a id="tree_314_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="食品、酒類、生鮮、特產"><span id="tree_314_ico" title="" treenode_ico="" class="button ico_close" style=""></span><span id="tree_314_span" class="node_name">食品、酒類、生鮮、特產</span></a></li><li id="tree_359" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_359_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_359_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="營養保健"><span id="tree_359_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_359_span" class="node_name">營養保健</span></a></li><li id="tree_360" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_360_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_360_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="圖書、音像、電子書"><span id="tree_360_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_360_span" class="node_name">圖書、音像、電子書</span></a></li><li id="tree_361" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_361_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_361_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="彩票、旅行、充值、票務"><span id="tree_361_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_361_span" class="node_name">彩票、旅行、充值、票務</span></a></li><li id="tree_362" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_362_switch" title="" class="button level0 switch center_docu" treenode_switch=""></span><a id="tree_362_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="理財、眾籌、白條、保險"><span id="tree_362_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_362_span" class="node_name">理財、眾籌、白條、保險</span></a></li><li id="tree_363" class="level0" tabindex="0" hidefocus="true" treenode=""><span id="tree_363_switch" title="" class="button level0 switch bottom_docu" treenode_switch=""></span><a id="tree_363_a" class="level0" treenode_a="" onclick="" target="_blank" style="" title="虛擬商品"><span id="tree_363_ico" title="" treenode_ico="" class="button ico_docu" style=""></span><span id="tree_363_span" class="node_name">虛擬商品</span></a></li></ul>



基於zTree的Jsp通用動態級聯樹結構