在项目中,通常会需要对用户的访问权限做一个限制和区分,即经典的 用户 – 角色 – 菜单 角色管理架构。在这个架构中,用户和角色的关系基本确定,即多对一的关系;而角色和菜单之前,其实还增加了“菜单操作”这样的操作权限,例如某个角色拥有的菜单操作权限如下图:
菜单和操作权限是一对多的关系,使用 springbootjpa 的实体类分别是
菜单:
@Entity
@Table(name = "menu", uniqueConstraints = { @UniqueConstraint(name = "idx_menuname", columnNames = { "menuName"}) })
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler"})
public class Menu implements Serializable {
private static final long serialVersionUID = -6499256046633708586L;
@Id
@Column(columnDefinition = "varchar(64) comment' 菜单 id'")
private String menuId; // 菜单 ID
@Column(nullable = false, columnDefinition = "varchar(255) comment' 菜单名称 '")
private String menuName; // 菜单名称
@OneToMany(mappedBy = "menu", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<MenuHandle> menuHandles;// 菜单操作权限
}
菜单操作权限:
@Entity
@Table(name = "menu_handle")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler"})
public class MenuHandle implements Serializable {
private static final long serialVersionUID = -5909986386327673973L;
@Id
@Column(columnDefinition = "varchar(64) comment' 操作权限 id'")
private String handleId; // 操作权限 id
@Column(nullable = false, columnDefinition = "varchar(255) comment' 权限名称 '")
private String name; // 权限名称
@ManyToOne(targetEntity = Menu.class)
@JoinColumn(name = "menu_id", updatable = false)
private Menu menu;// 权限对应菜单
}
角色和菜单是多对多的关系,角色和操作也是多对多的关系
角色:
@Entity
@Table(name = "role", uniqueConstraints = { @UniqueConstraint(name = "idx_rolename", columnNames = { "roleName"}) })
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler"})
public class Role implements Serializable {
private static final long serialVersionUID = -5553646385121286353L;
@Id
@Column(columnDefinition = "varchar(64) comment' 角色 id'")
private String roleId;
@Column(nullable = false, columnDefinition = "varchar(255) comment' 角色名称 '")
private String roleName;
@ManyToMany
private List<Menu> menus;// 角色的菜单
@ManyToMany
private List<MenuHandle> roleMenuHandles;// 角色的操作权限
}
那么在这个设计中,当我通过 springbootjpa api 查询某个角色时,角色的 menus 和 roleMenuHandles 就会无限循环级联查询,导致查询的对象生成不了正确的 json。
我当前的做法是:在权限实体中重写 toString 方法:
@Override
public String toString() {JSONObject jso = new JSONObject();
jso.put("handleId", handleId);
jso.put("name", name);
jso.put("menuId", menu.getMenuId());
return jso.toJSONString();}
如有更好的做法,欢迎补充。