在保存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. java日期比较,日期计算

    版权声明:本文为楼主原创文章,未经楼主允许不得转载,如要转载请注明来源. 都是常用的日期之间的比较方法,供以后参考. 热身:获取当前时间 SimpleDateFormat df = new Simpl ...

  2. (Forward) Music Player: From UI Proposal to Code

    Some developers have difficult to code when the UI proposal is a bit “sophisticated” or “complex”. M ...

  3. 通过案例对 spark streaming 透彻理解三板斧之一: spark streaming 另类实验

    本期内容 : spark streaming另类在线实验 瞬间理解spark streaming本质 一.  我们最开始将从Spark Streaming入手 为何从Spark Streaming切入 ...

  4. PCI Express(三) - A story of packets, stack and network

    原文出处:http://www.fpga4fun.com/PCI-Express3.html Packetized transactions PCI express is a serial bus. ...

  5. html-css实例

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  6. 网络存储技术介绍(1) ( based on zt)

    最近由于某同学微信发了一些网络存储的文章,开始感兴趣,稍微收集了一些 一.  网络存储技术 http://ask.zol.com.cn/q/187044.html  (yxr:很老的技术介绍吧) 网络 ...

  7. C# WinForm 单例模式(例:同一个窗体只创建一次实例)

    //C# WinForm 单例模式(例:同一个窗体只创建一次实例) //打开窗体的事件: Form3 f = Form3.InstanceObject() ; //实例化窗体 f.Focus(); / ...

  8. android Studio项目运行时报错“Could not identify launch activity: Default Activity not found”

    出现红色的小叉叉,有点蒙圈的感觉 其实只是因为AndroidManifest.xml里面没有设置运行初始的activity <activity android:name=".MainA ...

  9. JDBC学习

    JDBC全称 Java DataBase Connectivity(java数据库连接)可以为多种数据库提供统一的访问: 步骤:1:加载驱动程序: 加载Mysql驱动:Class.forName(&q ...

  10. POSIX信号处理

    信号用于通知进程发生了某件事情,可以由一个进程发给另一个进程,也可以由内核发个一个进程. 每个信号都有一个关联的行为,可以通过sigaction函数来设置一个信号的行为,有3种选择: 1.定义一个信号 ...