问题描述
我用SSH框架做权限管理时遇到一个奇怪问题:用户表:T_USER角色表:T_ROLE菜单表:T_RESOURCE角色用户表:T_USER_ROLE角色资源表:T_ROLE_RESOURCE我在修改角色时,如果Struts2的action设置为@Scope("prototype")时,会删除角色用户表和角色资源表数据:Hibernate:updateT_ROLEsetUPDATE_DATE=?whereID=?Hibernate:deletefromT_ROLE_RESOURCEwhereROLE_ID=?Hibernate:deletefromT_USER_ROLEwhereROLE_ID=?如果去掉@Scope("prototype"),更新正常:Hibernate:updateT_ROLEsetUPDATE_DATE=?whereID=?角色表POJO如下:@Entity@org.hibernate.annotations.Entity(selectBeforeUpdate=true,dynamicInsert=true,dynamicUpdate=true)@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)@Table(name="T_ROLE")publicclassRoleextendsAuditModelimplementsSerializable{privatestaticfinallongserialVersionUID=1L;@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="ID",nullable=false)privateLongid;@Column(name="NAME_ZH",length=64,nullable=false)privateStringnameZh;@Column(name="NAME_EN",length=64,nullable=false)privateStringnameEn;@Column(name="ROLE_CODE",length=30,nullable=false)privateStringroleCode;@Column(name="DESCRIPTION",length=64)privateStringdescription;@ManyToMany(cascade={CascadeType.MERGE},fetch=FetchType.LAZY)@JoinTable(name="T_ROLE_RESOURCE",joinColumns={@JoinColumn(name="ROLE_ID")},inverseJoinColumns={@JoinColumn(name="RESOURCE_ID")})privateSet<Resource>tsResources;@ManyToMany(cascade={CascadeType.MERGE},fetch=FetchType.LAZY)@JoinTable(name="T_USER_ROLE",joinColumns={@JoinColumn(name="ROLE_ID")},inverseJoinColumns={@JoinColumn(name="USER_ID")})privateSet<User>tsUsers=newHashSet<User>(0);@TransientprivateBooleanischecked=false;publicRole(){}publicLonggetId(){returnthis.id;}publicStringgetNameZh(){returnnameZh;}publicvoidsetNameZh(StringnameZh){this.nameZh=nameZh;}publicStringgetNameEn(){returnnameEn;}publicvoidsetNameEn(StringnameEn){this.nameEn=nameEn;}publicStringgetRoleCode(){returnroleCode;}publicvoidsetRoleCode(StringroleCode){this.roleCode=roleCode;}publicStringgetDescription(){returnthis.description;}publicSet<Resource>getTsResources(){returnthis.tsResources;}publicvoidsetTsResources(Set<Resource>tsResources){this.tsResources=tsResources;}publicSet<User>getTsUsers(){returnthis.tsUsers;}publicvoidsetDescription(Stringdescription){this.description=description;}publicvoidsetId(Longid){this.id=id;}publicvoidsetTsUsers(Set<User>tsUsers){this.tsUsers=tsUsers;}publicBooleangetIschecked(){returnischecked;}publicvoidsetIschecked(Booleanischecked){this.ischecked=ischecked;}}
解决方案
解决方案二:
这个问题很奇怪,没有发现过这个问题,可能需要看源码.区别应该是这样:(1)scope="prototype"(多态)是在每次用户发起请求时重新生成action对象,对于多线程访问不会出现问题,如果没有配置scope=prototype则添加的时候不会新建一个action,他任然会保留上次访问的过记录的信息。(2)默认是scope="singleton"(单态),这些bean被spring初始化后,始终只有一份,很适用于无状态的bean,DAO、Service都采用的这种。当然,scope的值还有session,request等等。(3)希望解决以后附上原因,解决过程中是可以学到很多知识的,特别是看过源码之后就会了解.
解决方案三:
你修改的时候是不是直接用的update()方法?
解决方案四:
使用merge方法试一试
解决方案五:
是调用的update方法:@Overridepublic<T>Tupdate(Tt){returnbaseDao.update(t);}
解决方案六:
经过测试使用merge方法可以的,但是什么原因呢,据我所知,merge是hibernate又new的了对象,把要更新的对象拷贝到new的对象里面,执行完成后new的对象是持久状态,而之前的对象还是托管状态。
解决方案七:
不好意思,merge也不行,我刚才测试时是因为把,角色用户表:T_USER_ROLE,角色资源表:T_ROLE_RESOURCE两张表数据删除了,没有出现删除语句。