在保存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;
}

ManyToMany【项目随笔】关于异常object references an unsaved transient instance的更多相关文章

  1. object references an unsaved transient instance【异常】

    [异常提示] TransientObjectException: object references an unsaved transient instance -save the transient ...

  2. object references an unsaved transient instance - save the transient instance before flushing异常问题处理

    一.异常:org.hibernate.TransientObjectException: object references an unsaved transient instance - save ...

  3. object references an unsaved transient instance - save the transient instance before flushing错误

    异常1:not-null property references a null or transient value解决方法:将“一对多”关系中的“一”方,not-null设置为false(参考资料: ...

  4. 三大框架常遇的错误:hibernate : object references an unsaved transient instance

    hibernate : object references an unsaved transient instance 该错误是操作顺序的问题,比如: save或update顺序问题---比方学生表和 ...

  5. ERROR org.hibernate.internal.SessionImpl - HHH000346: Error during managed flush [object references an unsaved transient instance - save the transient instance before flushing: cn.itcast.domain.Custom

    本片博文整理关于Hibernate中级联策略cascade和它导致的异常: Exception in thread "main" org.hibernate.TransientOb ...

  6. Hibernate的一个问题object references an unsaved transient instance - save the transi5

    1 我做了一对多和多对一的双向关联关系,在User这一方@ManyToOne已经设置了级联Cascade,这样在测试程序中保存User时,Group也应该自动保存,为什么会抛出以下的异常: (我是按着 ...

  7. object references an unsaved transient instance - save the transient instance before flushing: com.jspxcms.core.domain.ScTeam

    object references an unsaved transient instance - save the transient instance before flushing: com.j ...

  8. object references an unsaved transient instance save the transient instance before flushing

    object references an unsaved transient instance save the transient instance before flushing 对象引用未保存的 ...

  9. hibernate 对象状态异常:object references an unsaved transient instance - save the transient instance before flushing

    我的问题出在,删除的对象对应的表中有一个外键,关联着另外一个表,可是另外一个表中没有数据,所以报了这个错误. 参考http://www.cnblogs.com/onlywujun/archive/20 ...

随机推荐

  1. Could not load file using Ranorex runtime : General Questions

    如果你将编译好的bin文件夹复制到另一个未安装Ranorex程序的电脑上运行遇到如下错误信息 Could not load file or assembly 'Ranorex.Core, Versio ...

  2. C# 指定物理目录下载文件,Response.End导致“正在中止线程”异常的问题

    FileHandler http://www.cnblogs.com/vipsoft/p/3627709.html UpdatePanel无法导出下载文件: http://www.cnblogs.co ...

  3. C/C++ 右值引用 及 函数调用栈剖析

    参考: [1]. C/C++堆栈指引: http://www.cnblogs.com/Binhua-Liu/archive/2010/08/24/1803095.html [2]. C++临时变量的生 ...

  4. 单机运行环境搭建之 --CentOS-6.5安装配置Tengine

    一.安装pcre:   cd /usr/local/src wget http://downloads.sourceforge.net/project/pcre/pcre/8.34/pcre-8.34 ...

  5. 关于CacheLookup一个有趣的问题

    今天写一个与其他系统进行物料同步的接口,通过COM Business Connector调用Axapta3.0的方法将数据插入到物料表中,中间发生异常,事务回滚,再次调用的时候提示刚刚发生异常的物料已 ...

  6. mysql分区查询

    SELECT *FROM INFORMATION_SCHEMA.partitions WHERE table_name='表名' and table_schema='数据库名'

  7. Python 单例

    方法1: 1 class Singleton(object): def __new__(cls, *args, **kwargs): if '_inst' not in vars(cls): cls. ...

  8. 深入理解js——原型的灵活性

    在java中,class是一个模子,对象就是按照这个模子刻出来的:但是在JavaScript中对象可以刻成任意的样子. 首先,对象属性可以随时改动.对象或者函数,刚开始new出来之后,可能啥属性都没有 ...

  9. textview 多行 省略号

    TextView自带的可以通过 android:ellipsize="end" android:singleLine="true"实现单行省略,  多行显示: ...

  10. JavaScript实例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...