zoukankan      html  css  js  c++  java
  • ManyToMany【项目随笔】关于异常object references an unsaved transient instance

    在保存ManyToMany  时出现异常: 

    org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance

    如图:

    出现原因:单向ManyToMany保存顺序反了,应当先保存主控端permission对象

    错误代码:

    @Transactional(readOnly=false)
        @Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
        @CacheEvict(value = "permissionList", allEntries = true)
        public Permission save(Permission permission) {
            permission.setMenu(menuDao.findOne(permission.getMenuId()));
            
            List<Role> roles = roleDao.findByDataScope(DataScope.ALL.getValue());
            for(Role temp : roles){
                List <Permission> permissions = temp.getPermissions();
                permissions.add(permission);
            }
            roleDao.save(roles);
            permission.setRoles(roles);  //权限归属于该角色
            return permissionDao.save(permission);
        }

    两个类,角色Role和权限Permission,一个角色可以拥有多个权限,反之亦然。  

    代码如下:

    package net.myspring.blue.modules.sys.entity;
    
    import java.util.List;
    
    import javax.persistence.Cacheable;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.Table;
    import javax.persistence.Transient;
    
    import com.google.common.collect.Lists;
    
    import net.myspring.blue.common.persistence.DataEntity;
    import net.myspring.blue.common.utils.Collections3;
    
    
    /**
     * The persistent class for the sys_role database table.
     * 
     */
    @Entity
    @Table(name="sys_role")
    @Cacheable
    public class Role extends DataEntity {
        private String code;
        private Integer dataScope;
        private String name;
        private List<Permission> permissions=Lists.newArrayList();
        private List<User> users=Lists.newArrayList();
        
        private List<Long> permissionIds=Lists.newArrayList();
    
        public Role() {
        }
    
        public String getCode() {
            return this.code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        @Column(name="data_scope")
        public Integer getDataScope() {
            return this.dataScope;
        }
    
        public void setDataScope(Integer dataScope) {
            this.dataScope = dataScope;
        }
    
        public String getName() {
            return this.name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        //bi-directional many-to-many association to Permission
        @ManyToMany
        @JoinTable(name = "sys_role_permission", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = { @JoinColumn(name = "permission_id") })
        public List<Permission> getPermissions() {
            return this.permissions;
        }
    
        public void setPermissions(List<Permission> permissions) {
            this.permissions = permissions;
        }
    
    
        //bi-directional many-to-many association to User
        @ManyToMany(mappedBy="roles")
        public List<User> getUsers() {
            return this.users;
        }
    
        public void setUsers(List<User> users) {
            this.users = users;
        }
    
        @SuppressWarnings("unchecked")
        @Transient
        public List<Long> getPermissionIds() {
            if(permissionIds!=null && permissionIds.size()==0 && Collections3.isNotEmpty(permissions)) {
                permissionIds= Collections3.extractToList(permissions, "id");
            }
            return permissionIds;
        }
    
        public void setPermissionIds(List<Long> permissionIds) {
            this.permissionIds = permissionIds;
        }
    }

    权限Permission类

    package net.myspring.blue.modules.sys.entity;
    
    import javax.persistence.*;
    
    import net.myspring.blue.common.config.Global;
    import net.myspring.blue.common.persistence.DataEntity;
    import net.myspring.blue.common.utils.Collections3;
    
    import com.google.common.collect.Lists;
    
    import java.util.List;
    
    
    /**
     * The persistent class for the sys_permission database table.
     * 
     */
    @Entity
    @Table(name="sys_permission")
    @Cacheable
    public class Permission extends DataEntity {
        private String name;
        private String permission;
        private Menu menu;
        private List<Role> roles=Lists.newArrayList();
        
        private Long menuId;
    
        public Permission() {
        }
    
        public String getName() {
            return this.name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    
        public String getPermission() {
            return this.permission;
        }
    
        public void setPermission(String permission) {
            this.permission = permission;
        }
    
        //bi-directional many-to-one association to Menu
        @ManyToOne(fetch=FetchType.LAZY)
        @JoinColumn(name="menu_id")
        public Menu getMenu() {
            return this.menu;
        }
    
        public void setMenu(Menu menu) {
            this.menu = menu;
        }
    
    
        //bi-directional many-to-many association to Role
        @ManyToMany(mappedBy="permissions")
        public List<Role> getRoles() {
            return this.roles;
        }
    
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }
        
        @Transient
        public Long getMenuId() {
            if(menuId==null && menu!=null) {
                menuId=menu.getId();
            }
            return menuId;
        }
    
        public void setMenuId(Long menuId) {
            this.menuId = menuId;
        }
    
        @Transient
        public String getRoleNames() {
            return Collections3.extractToString(roles, "name", Global.CHAR_COMMA);
        }
    }

    注意主控端是Permission类 ,注解“ @ManyToMany(mappedBy="permissions") ”说明了这点

    业务场景:

      admin角色是拥有"任意权限"的,我在添加新权限的时候,权限应当同步被admin所拥有。

    权限对应的的角色组成的List<Role>也应当等于拥有”任意权限"的角色 .->List<Role> roles = roleDao.findByDataScope(DataScope.ALL.getValue());

    保存时,一定要先save主控端permission,否则数据库将报错

    正确的写法

    @Transactional(readOnly=false)
        @Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
        @CacheEvict(value = "permissionList", allEntries = true)
        public Permission save(Permission permission) {
            permission.setMenu(menuDao.findOne(permission.getMenuId()));
            List<Role> roles = roleDao.findByDataScope(DataScope.ALL.getValue());
            permission.setRoles(roles);
            permissionDao.save(permission);  //注意save的顺序  permission先
            for(Role temp : roles){
                List <Permission> permissions = temp.getPermissions();
                permissions.add(permission);
            }
            roleDao.save(roles);  //roles后
            return null;
        }
  • 相关阅读:
    函数模板
    可以接收数量不定的参数的函数
    Poco库的学习
    分割字符串,字符串去除空格
    初始化时添加click方法
    【Mybatis】传Map与传String
    jsp全局变量
    【oracle】Oracle中字符串连接的实现方法【转】
    斜杠(右斜杠)【/】 与 反斜杠(右斜杠)【】
    【Java】@ResponseBody 返回JsonObject
  • 原文地址:https://www.cnblogs.com/ChenJunHacker/p/4586796.html
Copyright © 2011-2022 走看看