在保存ManyToMany  时出现异常:

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

如图:

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

错误代码:

  1. @Transactional(readOnly=false)
  2. @Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
  3. @CacheEvict(value = "permissionList", allEntries = true)
  4. public Permission save(Permission permission) {
  5. permission.setMenu(menuDao.findOne(permission.getMenuId()));
  6.  
  7. List<Role> roles = roleDao.findByDataScope(DataScope.ALL.getValue());
  8. for(Role temp : roles){
  9. List <Permission> permissions = temp.getPermissions();
  10. permissions.add(permission);
  11. }
  12. roleDao.save(roles);
  13. permission.setRoles(roles); //权限归属于该角色
  14. return permissionDao.save(permission);
  15. }

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

代码如下:

  1. package net.myspring.blue.modules.sys.entity;
  2.  
  3. import java.util.List;
  4.  
  5. import javax.persistence.Cacheable;
  6. import javax.persistence.Column;
  7. import javax.persistence.Entity;
  8. import javax.persistence.JoinColumn;
  9. import javax.persistence.JoinTable;
  10. import javax.persistence.ManyToMany;
  11. import javax.persistence.Table;
  12. import javax.persistence.Transient;
  13.  
  14. import com.google.common.collect.Lists;
  15.  
  16. import net.myspring.blue.common.persistence.DataEntity;
  17. import net.myspring.blue.common.utils.Collections3;
  18.  
  19. /**
  20. * The persistent class for the sys_role database table.
  21. *
  22. */
  23. @Entity
  24. @Table(name="sys_role")
  25. @Cacheable
  26. public class Role extends DataEntity {
  27. private String code;
  28. private Integer dataScope;
  29. private String name;
  30. private List<Permission> permissions=Lists.newArrayList();
  31. private List<User> users=Lists.newArrayList();
  32.  
  33. private List<Long> permissionIds=Lists.newArrayList();
  34.  
  35. public Role() {
  36. }
  37.  
  38. public String getCode() {
  39. return this.code;
  40. }
  41.  
  42. public void setCode(String code) {
  43. this.code = code;
  44. }
  45.  
  46. @Column(name="data_scope")
  47. public Integer getDataScope() {
  48. return this.dataScope;
  49. }
  50.  
  51. public void setDataScope(Integer dataScope) {
  52. this.dataScope = dataScope;
  53. }
  54.  
  55. public String getName() {
  56. return this.name;
  57. }
  58.  
  59. public void setName(String name) {
  60. this.name = name;
  61. }
  62.  
  63. //bi-directional many-to-many association to Permission
  64. @ManyToMany
  65. @JoinTable(name = "sys_role_permission", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = { @JoinColumn(name = "permission_id") })
  66. public List<Permission> getPermissions() {
  67. return this.permissions;
  68. }
  69.  
  70. public void setPermissions(List<Permission> permissions) {
  71. this.permissions = permissions;
  72. }
  73.  
  74. //bi-directional many-to-many association to User
  75. @ManyToMany(mappedBy="roles")
  76. public List<User> getUsers() {
  77. return this.users;
  78. }
  79.  
  80. public void setUsers(List<User> users) {
  81. this.users = users;
  82. }
  83.  
  84. @SuppressWarnings("unchecked")
  85. @Transient
  86. public List<Long> getPermissionIds() {
  87. if(permissionIds!=null && permissionIds.size()==0 && Collections3.isNotEmpty(permissions)) {
  88. permissionIds= Collections3.extractToList(permissions, "id");
  89. }
  90. return permissionIds;
  91. }
  92.  
  93. public void setPermissionIds(List<Long> permissionIds) {
  94. this.permissionIds = permissionIds;
  95. }
  96. }

权限Permission类

  1. package net.myspring.blue.modules.sys.entity;
  2.  
  3. import javax.persistence.*;
  4.  
  5. import net.myspring.blue.common.config.Global;
  6. import net.myspring.blue.common.persistence.DataEntity;
  7. import net.myspring.blue.common.utils.Collections3;
  8.  
  9. import com.google.common.collect.Lists;
  10.  
  11. import java.util.List;
  12.  
  13. /**
  14. * The persistent class for the sys_permission database table.
  15. *
  16. */
  17. @Entity
  18. @Table(name="sys_permission")
  19. @Cacheable
  20. public class Permission extends DataEntity {
  21. private String name;
  22. private String permission;
  23. private Menu menu;
  24. private List<Role> roles=Lists.newArrayList();
  25.  
  26. private Long menuId;
  27.  
  28. public Permission() {
  29. }
  30.  
  31. public String getName() {
  32. return this.name;
  33. }
  34.  
  35. public void setName(String name) {
  36. this.name = name;
  37. }
  38.  
  39. public String getPermission() {
  40. return this.permission;
  41. }
  42.  
  43. public void setPermission(String permission) {
  44. this.permission = permission;
  45. }
  46.  
  47. //bi-directional many-to-one association to Menu
  48. @ManyToOne(fetch=FetchType.LAZY)
  49. @JoinColumn(name="menu_id")
  50. public Menu getMenu() {
  51. return this.menu;
  52. }
  53.  
  54. public void setMenu(Menu menu) {
  55. this.menu = menu;
  56. }
  57.  
  58. //bi-directional many-to-many association to Role
  59. @ManyToMany(mappedBy="permissions")
  60. public List<Role> getRoles() {
  61. return this.roles;
  62. }
  63.  
  64. public void setRoles(List<Role> roles) {
  65. this.roles = roles;
  66. }
  67.  
  68. @Transient
  69. public Long getMenuId() {
  70. if(menuId==null && menu!=null) {
  71. menuId=menu.getId();
  72. }
  73. return menuId;
  74. }
  75.  
  76. public void setMenuId(Long menuId) {
  77. this.menuId = menuId;
  78. }
  79.  
  80. @Transient
  81. public String getRoleNames() {
  82. return Collections3.extractToString(roles, "name", Global.CHAR_COMMA);
  83. }
  84. }

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

业务场景:

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

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

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

正确的写法

  1. @Transactional(readOnly=false)
  2. @Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
  3. @CacheEvict(value = "permissionList", allEntries = true)
  4. public Permission save(Permission permission) {
  5. permission.setMenu(menuDao.findOne(permission.getMenuId()));
  6. List<Role> roles = roleDao.findByDataScope(DataScope.ALL.getValue());
  7. permission.setRoles(roles);
  8. permissionDao.save(permission); //注意save的顺序 permission先
  9. for(Role temp : roles){
  10. List <Permission> permissions = temp.getPermissions();
  11. permissions.add(permission);
  12. }
  13. roleDao.save(roles); //roles后
  14. return null;
  15. }

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. 洛谷P3367 【模板】并查集

    P3367 [模板]并查集 293通过 551提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 不知道哪错了 为啥通不过最后三个节点 题解 不懂为什么MLE 最后一个数 ...

  2. 【226】C# 相关功能实现代码

    目录: 1. 实现代码的等待操作 2. 实现文件夹/文件打开操作 3. 建立事件模板,然后调用 4. 用代码在Form中写控件,同时可以编写控件数组 5. 用代码执行事件   1. 实现代码的等待操作 ...

  3. 2016.02.17 JS DOM编程艺术 第四五六章

    看完这三章内容,集中精力,加快速度.

  4. jQuery之ajax的跨域获取数据

    如果获取的数据文件存放在远程服务器上(域名不同,也就是跨域获取数据),则需要使用jsonp类型.使用这种类型的话,会创建一个查询字符串参数 callback=? ,这个参数会加在请求的URL后面.服务 ...

  5. 《C++编程规范:101条规则、准则与最佳实践》学习笔记

    转载:http://dsqiu.iteye.com/blog/1688217 组织和策略问题 0. 不要为小事斤斤计较.(或者说是:知道什么东西不需要标准化) 无需在多个项目或者整个公司范围内强制实施 ...

  6. asp.net GridView控件的列属性

    BoundField 默认的数据绑定类型,通常用于显示普通文本 CheckBoxField 显示布尔类型的数据.绑定数据为TRUE时,复选框数据绑定列为选中状态:绑定数据为FALSE时,则显示未选中状 ...

  7. static 使用,静态变量

    由static修饰,属于整个类,被类对象共享, 可以由类名,对象名访问 static可以修饰变量,方法,代码块 public class HelloWorld { static String clas ...

  8. OpenSSL命令---passwd

    NAME passwd - compute password hashes SYNOPSIS openssl passwd [-crypt] [-1] [-apr1] [-salt string] [ ...

  9. Android消息推送——JPush极光推送

    刚看了一篇关于Android消息推送评测总结的博客http://www.cnblogs.com/logan/p/4514635.html: 自己也对原学过的JPush极光进行一下小结,方便后续工作使用 ...

  10. css控制页面打印(分页、屏蔽不需要打印的对象)

    样式: <style   media="print">     .Noprint   {   DISPLAY:   none;}     .PageNext   {   ...