角色映射表配置
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="zhongfucheng.role.entity.Role" table="role"> <id name="roleId" type="java.lang.String"> <column name="roleId" length="32" /> <generator class="uuid.hex" /> </id> <property name="state" type="java.lang.String"> <column name="state" length="1" /> </property> <property name="name" type="java.lang.String"> <column name="name" length="20" not-null="true" /> </property> <!-- 一方维护多方的数据,inverse设置为true,没有控制权限 设置级联保存更新,在保存角色的时候,将权限也保存起来了。 不设置懒加载,直接获取到权限的数据 --> <set name="rolePrivilegeSet" lazy="false" inverse="true" cascade="save-update" > <key> <column name="role_id"></column> </key> <one-to-many class="zhongfucheng.role.entity.RolePrivilege" ></one-to-many> </set> </class> </hibernate-mapping>
- 一的一方之所以将控制反转设置为ture,就是让多的一方维护一的一方数据。因为
多个一方维护一的一方数据的时候,SQL语句会比一的一方维护多的一方的SQL语句要少。
------ - - - -更新
上面我们是将inverse属性设置为true的,但是下面的代码还是使用了一的一方来维护多个一方的数据。这样是不合理的。
- 讲道理的是:inverse的优先级是比casede要高的,也就是说,当我们设置了inverse属性为true的时候,cascade属性是无效的。
- 因此,可能我当时修改了没发现吧。如果程序运行不起来,就是这里的问题了。
角色与权限映射表配置
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="zhongfucheng.role.entity.RolePrivilege" table="role_privilege"> <composite-id name="id" class="zhongfucheng.role.entity.CompositeKey"> <key-many-to-one name="role" class="zhongfucheng.role.entity.Role" lazy="false"> <column name="role_id "></column> </key-many-to-one> <key-property name="code" type="java.lang.String"> <column name="code"></column> </key-property> </composite-id> </class> </hibernate-mapping>
Role模块的CRUD
没啥好说的,我们在User模块中已经写过了。我们可以直接复制过来,然后将不要的功能去掉。
- 将全部的User改成Role
- 将全部的user改成role
dao-->service--->action这样改完,就有了Role模块的CRUD了。
最后:
- Spring总配置文件中加载role模块实体映射文件,加载role模块的bean文件。
- Struts总配置文件中加载role模块的Struts配置文件。
添加模块
把权限的集合带过去给JSP页面显示出来,JSP使用Struts的checkbox进行遍历【很好用】
public String addUI() { ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP); return "addUI"; }
使用checkbox标签遍历
<tr> <td class="tdBg" width="200px">角色权限:</td> <td> <%-- checkboxlist:自动把Map集合遍历出来,生成对应的key value,Map集合的key作为checkbox的key,value作为checkbox的value list:集合 name:把数据带过去给服务器 --%> <s:checkboxlist list="#privilegeMap" name="privilegeIds"/> </td> </tr>
这里写图片描述
这里写图片描述
/************数据自动封装权限的id*************************/ private String[] privilegeIds; public String[] getPrivilegeIds() { return privilegeIds; } public void setPrivilegeIds(String[] privilegeIds) { this.privilegeIds = privilegeIds; }
处理角色与权限的关系。在配置中使用了级联保存,因此可以直接保存数据
public String add() throws IOException { if (role != null) { //处理角色与权限的关系 if (privilegeIds != null) { HashSet<RolePrivilege> set = new HashSet<>(); //得到每一个权限的值--->entity给出对应的构造方法... for (int i = 0; i < privilegeIds.length; i++) { set.add(new RolePrivilege(new CompositeKey(role, privilegeIds[i]))); } role.setRolePrivilegeSet(set); } roleServiceImpl.save(role); //跳转到列表显示页面 return "list"; } return null; }
这里写图片描述
这里写图片描述
显示模块
在显示模块中,主要是显示角色的权限中有点绕…..
角色的权限用set集合保存起来,set集合元素是角色与权限的关系,角色与权限是一个类,该类保存着主键类,主键类存储的是角色和权限code。
我们的目的是:得到角色含有的权限。而目前为止,我们最多只能得到每个权限code值:
而我们想要显示的是权限的名称,于是我们得把权限集合传过去,根据code得到权限的名称:
public String listUI() { roleList = roleServiceImpl.findObjects(); ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP); return "listUI"; }
JSP页面取值:注意懒加载的问题,设定不要懒加载。不然会出现: java.io.IOException: Stream closed
<s:iterator value="rolePrivilegeSet"> <s:property value="#privilegeMap[compositeKey.code]"/> </s:iterator>
这里写图片描述
单个删除功能
跳转到Action中处理,把id传递过去…
function doDelete(id) { document.forms[0].action = "${basePath}role/role_delete.action?role.roleId="+id; document.forms[0].submit(); }
判断是否为空,不为空就删除。返回到列表页面
2017/5/31 12:59:27 //删除 public String delete() { if (role != null && role.getRoleId() != null) { roleServiceImpl.delete(role.getRoleId()); } return "list"; }
修改模块
数据回显页面,主要就是角色的权限那里怎么回显。我们把所有的权限带过去,用字符串数组记录当前角色有什么权限
//得到所有的权限 ActionContext.getContext().getContextMap().put("privilegeMap", Constant.PRIVILEGE_MAP); //外边已经传了id过来了,我们要找到id对应的Role if (role != null && role.getRoleId() != null) { //直接获取出来,后面JSP会根据Role有getter就能读取对应的信息! role = roleServiceImpl.findObjectById(role.getRoleId()); //得到角色所有的权限,把它封装到privilegeIds字符数组中。 //处理权限回显 if (role.getRolePrivilegeSet() != null) { privilegeIds = new String[role.getRolePrivilegeSet().size()]; int i = 0; for (RolePrivilege rp : role.getRolePrivilegeSet()) { privilegeIds[i++] = rp.getCompositeKey().getCode(); } } } return "editUI";
在JSP页面,使用checkboxlist标签进行遍历。
<s:checkboxlist list="#privilegeMap" name="privilegeIds" ></s:checkboxlist>
这里写图片描述
得到JSP传递过来的ids,封装成一个set集合。将set集合赋值给role对象。
public String edit() throws IOException { //Struts2会自动把JSP带过来的数据封装到Role对象上 if (role.getRoleId() != null && role != null) { Set<RolePrivilege> set = new HashSet<>(); //得到修改的权限id,封装到set集合中。 for (String privilegeId : privilegeIds) { set.add(new RolePrivilege(new CompositeKey(role, privilegeId))); } role.setRolePrivilegeSet(set); roleServiceImpl.update(role); } return "list"; }
仅仅是使用update(role)方法是不够的,因此Hibernate在更新操作的时候,会先把数据查询出来。当我们更改角色权限的时候,它会将我们已有的权限保留下来,如果有新的就继续添加。它不会把我们没勾选的剔除的。
因此,我们需要在更新的之前,把当前角色所有的权限给删了。
//在修改之前,把角色的所有权限给删除了。不然会遗留之前的权限下来。 roleDaoImpl.deleteRolePrivilegeByRoleId(role.getRoleId());
/*** * 根据角色id删除所有的权限 * */ @Override public void deleteRolePrivilegeByRoleId(String roleId) { String sql = "DELETE FROM RolePrivilege WHERE compositeKey.role.roleId= ?"; Query query = getSession().createQuery(sql); query.setParameter(0, roleId); query.executeUpdate(); }
效果:
这里写图片描述