Spring Data JPA 权限记录转权限树形结构解析

虾米姐 阅读:592 2021-03-31 13:19:42 评论:0

第一步:权限表permission

DROP TABLE IF EXISTS `permission`; 
CREATE TABLE `permission`  ( 
  `permission_id` int(11) NOT NULL COMMENT '主键id', 
  `permission_zh` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单中文名称', 
  `permission_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单英文名称', 
  `permission_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单路径', 
  `permision_icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单图标', 
  `permision_component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '前端路由所在的组件位置', 
  `permision_parent_id` int(11) NULL DEFAULT NULL COMMENT '父菜单', 
  PRIMARY KEY (`permission_id`) USING BTREE, 
  INDEX `permission_zh`(`permission_zh`) USING BTREE 
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

第二步:spring data jpa 对应实体映射表

package com.zzg.entity; 
 
import javax.persistence.Entity; 
import javax.persistence.Id; 
 
import lombok.Getter; 
import lombok.Setter; 
 
/** 
 *  
 * @author zzg 
 * 
 */ 
@Getter 
@Setter 
@Entity 
public class Permission { 
 
    @Id 
    private Integer permissionId; 
    private String permissionName; 
    private String permissionZh; 
    private String permissionPath; 
    private String permisionIcon; 
    private String permisionComponent; 
    private Integer permisionParentId; 
     
//    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)    
//    @JoinColumn(name="permision_parent_id")   
//    private Permission parent; 
//    // 子菜单项 
//    @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.EAGER)   
//    private Set<Permission> child  = new HashSet<Permission>() ; 
} 

问题描述:在权限表中(permission),存在父子关系(树形结构关系),为了标识这种关系我最初开始采用的方式是使用spring data jpa 提供的关系注解标签:@ManyToOne、@JoinColumn、@OneToMany。采用这种方式可以很快在父子关系(树形结构)关系的表述,但是在实际情况验证中,由于采用关系注解标签,导致查询数据关系混乱(简单来说:就是数据之间嵌套严重)。我这里采用的方法是放弃注解标签,通过自定义封装实体对象,包含父子关系(树形结构关系)。

第三步:Permission 实体封装包装对象。

package com.zzg.vo; 
 
import java.util.List; 
 
import lombok.Getter; 
import lombok.Setter; 
 
@Getter 
@Setter 
public class PermissionVo { 
	private Integer permissionId; 
	private String permissionName; 
	private String permissionZh; 
	private String permissionPath; 
	private String permisionIcon; 
	private String permisionComponent; 
	private Integer permisionParentId; 
	private List<PermissionVo> child; 
} 

第四步:Controller 查询指定用户所拥有的权限信息(permission ),方法:@RequestMapping(value = "/permission/{uid}", method = RequestMethod.GET)

package com.zzg.controller; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.Optional; 
import javax.persistence.criteria.CriteriaBuilder; 
import javax.persistence.criteria.CriteriaQuery; 
import javax.persistence.criteria.Predicate; 
import javax.persistence.criteria.Root; 
 
import org.apache.shiro.util.CollectionUtils; 
import org.springframework.beans.BeanUtils; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.jpa.domain.Specification; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 
import com.zzg.common.AbstractController; 
import com.zzg.dao.PermissionRepository; 
import com.zzg.dao.RoleRepository; 
import com.zzg.dao.UserRepository; 
import com.zzg.entity.Permission; 
import com.zzg.entity.Role; 
import com.zzg.entity.User; 
import com.zzg.vo.PermissionVo; 
 
@RestController 
public class PermissionController extends AbstractController{ 
	@Autowired 
	private PermissionRepository permissionRepository; 
	@Autowired 
	private UserRepository userRepository; 
	@Autowired 
	private RoleRepository roleRepository; 
	 
	 
	@RequestMapping(value = "/permission/save", method = RequestMethod.POST) 
	@ResponseBody 
	public Map insert(@RequestBody Permission permission) { 
		permissionRepository.save(permission); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "新增成功"); 
		return map; 
	} 
	 
	/** 
	 * 动态更新:仅限于更新单表字段 
	 * @param house 
	 * @return 
	 */ 
	@RequestMapping(value = "/permission/update", method = RequestMethod.POST) 
	@ResponseBody 
	public Map update(@RequestBody Permission permission) { 
		Optional<Permission> old = permissionRepository.findById(permission.getPermissionId()); 
		if(old.isPresent()){ 
			Permission oldPermission = old.get(); 
            //将传过来的 house 中的非NULL属性值复制到 oldHouse 中 
            copyPropertiesIgnoreNull(permission, oldPermission); 
            //将得到的新的 oldHouse 对象重新保存到数据库,因为数据库中已经存在该记录 
            //所以JPA会很智能的 改为更新操作,更新数据库 
            permissionRepository.save(oldPermission); 
        } 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "更新成功"); 
		return map; 
	} 
	 
	@RequestMapping(value = "/permission/findPage", method = RequestMethod.POST) 
	@ResponseBody 
	public Map findPage(@RequestBody Map<String, Object> paramter) { 
		//显示第1页每页显示3条 
		PageRequest pr = super.initPageBounds(paramter); 
		 
		Page<Permission> stus = permissionRepository.findAll(new Specification<Permission>(){ 
			@Override 
			public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { 
				// TODO Auto-generated method stub 
				List<Predicate> predicateList = new ArrayList<>(); 
				 
				return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()])); 
			} 
		}, pr); 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", stus); 
		return map; 
	} 
	 
	/** 
	 * 查询用户指定权限 
	 * @param uid 
	 * @return 
	 */ 
	@RequestMapping(value = "/permission/{uid}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map findPermission(@PathVariable Integer uid) { 
		List<PermissionVo> permissionsVos = new ArrayList<PermissionVo>(); 
		 
		List<Permission> permissions = new ArrayList<Permission>(); 
		//显示第1页每页显示3条 
		User user = userRepository.findByUserId(uid); 
		 
		user.getRoles().stream().forEach(item->{ 
        	Role role = roleRepository.findByRoleId(item.getRoleId()); 
        	if(!CollectionUtils.isEmpty(role.getPermissions())){ 
        		for(Permission permission : role.getPermissions()){ 
        			if(permission.getPermisionParentId() == null){ 
        				permissions.add(permission); 
        			} 
        			 
        		} 
        	} 
        }); 
		 
	 
		 
		 
		permissions.stream().forEach(item ->{ 
			  
			 /** 
			  * Spring Data JPA 动态查询条件 
			  */ 
			 Specification<Permission> specification = new Specification<Permission>() { 
	             @Override 
	            public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> cq, CriteriaBuilder cb) { 
	                List<Predicate> predicates = new ArrayList<Predicate>(); 
	                if(null != item.getPermissionId()) { 
	                    predicates.add(cb.equal(root.<Integer>get("permisionParentId"), item.getPermissionId())); 
	                } 
	                return cq.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); 
	            } 
	        }; 
	        List<Permission> childPermission = permissionRepository.findAll(specification); 
	        List<PermissionVo> childPermissionVO = new ArrayList<PermissionVo>(); 
	        for(Permission permission : childPermission){ 
	        	 PermissionVo vo = new PermissionVo(); 
	        	 BeanUtils.copyProperties(permission, vo); 
	        	 childPermissionVO.add(vo); 
	        } 
	         
	        PermissionVo vo = new PermissionVo(); 
	        BeanUtils.copyProperties(item, vo); 
	        vo.setChild(childPermissionVO); 
	         
	        permissionsVos.add(vo); 
	         
		}); 
		  
		 
		// 数据清理 
//		Iterator<Permission> iterator = permissions.iterator(); 
//		while(iterator.hasNext()){ 
//			Permission permission = iterator.next(); 
//			if(permission.getPermisionParentId() != null){ 
//				iterator.remove(); 
//			} 
//		} 
		 
		 
 
//		for(Permission permission : permissions){ 
//			if(permission.getParent() != null){ 
//				permissions.remove(permission); 
//			} 
//		} 
				 
		Map<String, Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "查询成功"); 
		map.put("date", permissionsVos); 
		return map; 
	} 
	 
	@RequestMapping(value = "/permission/delete/{id}", method = RequestMethod.GET) 
	@ResponseBody 
	public Map delete(@PathVariable("id") Integer id) { 
		permissionRepository.deleteById(id); 
		Map<String,Object> map = new HashMap<String, Object>(); 
		map.put("code", 200); 
		map.put("message", "删除成功"); 
		return map; 
	} 
 
} 

效果战术:

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

我的关注

全民解析

搜索
关注我们