我在使用雙向Many-to-one關系時,想實現數據字典管理,1的一端是數據字典類別比如"性別","學歷",many一端通過外鍵進行引用.
1.單獨對1的一端進行crud都沒有問題,建好連接以后,刪除1端,many同時刪除有聯系的記錄
2.設置好了表間的聯系.進行CRD沒啥問題.update的時候,不對外鍵進行任何修改時.正常運行.修改外鍵時,報如下錯誤
?javax.servlet.ServletException: org.springframework.orm.hibernate3.HibernateSystemException: identifier of an instance of com.skycity.office.bean.DictType was altered from 4028898e1ae1d3d6011ae1d4dea70001 to 4028898e1abd9f87011abdc769de0003; nested exception is org.hibernate.HibernateException: identifier of an instance of com.skycity.office.bean.DictType was altered from 4028898e1ae1d3d6011ae1d4dea70001 to 4028898e1abd9f87011abdc769de0003
網上找了很久.有的說不是many-to-many的問題.很多地方說什么merge().saveOrUpdate(),嘗試了很多,網上詳細的解決方案也沒有.將修改時調用的方法注釋了,還是會出現這種錯誤.有點崩潰的感覺
試了merge().這里提到merge()也碰到一個奇怪的問題.merge按正常來說應該是合并的意思.我在many端修改時.使用了merge,居然one端進行了修改
比如.我想將"性別"為"女"的類型改成"學歷"(當然這是我測試),他最后修改了我的字典類別表,將"性別"類別改成了"學歷"類別.不知道是什么原因.
貼出我的部分代碼:
字典類別表的POJO
package com.skycity.office.bean;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "PFDICTTYPE")
public class DictType extends IdEntity{
?private String name;
?private String type;
?
?private Set<DictCode> dictCode=new HashSet<DictCode>();
?
?public String getName() {
??return name;
?}
?
?public void setName(String name) {
??this.name = name;
?}
?
?public String getType() {
??return type;
?}
?public void setType(String type) {
??this.type = type;
?}
?@OneToMany(mappedBy="dictType",cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
?public Set<DictCode> getDictCode() {
??return dictCode;
?}
?public void setDictCode(Set<DictCode> dictCode) {
??this.dictCode = dictCode;
?}
}
字典表的POJO
package com.skycity.office.bean;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "PFDICTCODE")
public class DictCode extends IdEntity{
??? private String dictName;
??? private String dictDesc;
??? private String dictValue;
???
??? private DictType dictType;
?@ManyToOne(cascade = { CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.LAZY)??
?@JoinColumn(name = "dictType",nullable = false,updatable=true,insertable = true)
??? public DictType getDictType() {
??? ?return dictType;
??? }
?public String getDictName() {
??return dictName;
?}
?public void setDictName(String dictName) {
??this.dictName = dictName;
?}
?public String getDictDesc() {
??return dictDesc;
?}
?public void setDictDesc(String dictDesc) {
??this.dictDesc = dictDesc;
?}
?public void setDictType(DictType dictType) {
??this.dictType = dictType;
?}
?
?public String getDictValue() {
??return dictValue;
?}
?
?public void setDictValue(String dictValue) {
??this.dictValue = dictValue;
?}
?
?@SuppressWarnings("unchecked")
?@Transient
?public List<String> getCheckedDictTypeIds() throws Exception {
??return null;// CollectionUtils.collectAsList(roles, "id");
?}
}
DictCode表的Service實現
package com.skycity.office.service.impl;
import java.sql.SQLException;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.hibernate.Page;
import org.springside.modules.orm.hibernate.SimpleHibernateTemplate;
import com.skycity.office.bean.DictCode;
import com.skycity.office.bean.DictType;
@Service
@Transactional(readOnly = true)
public class DictCodeServiceImpl{
?private SimpleHibernateTemplate<DictCode, String> dictCodeDAO;
?private SimpleHibernateTemplate<DictType, String> dictTypeDAO;
?
?@Autowired
?public void setSessionFactory(SessionFactory sessionFactory) {
??dictCodeDAO = new SimpleHibernateTemplate<DictCode, String>(sessionFactory, DictCode.class);
??dictTypeDAO = new SimpleHibernateTemplate<DictType, String>(sessionFactory, DictType.class);
?}
?
?public Page<DictCode> getAllDictCodes(Page<DictCode> page) {
??return dictCodeDAO.findAll(page);
?}
?public DictCode getDictCode(String id) {
??return dictCodeDAO.get(id);
?}
?
?public List<DictType> getAllDictTypes() {
??return dictTypeDAO.findAll();
?}
DictCode Action:
package com.skycity.office.web.action;
import java.util.List;
import org.apache.struts2.config.ParentPackage;
import org.apache.struts2.config.Result;
import org.apache.struts2.config.Results;
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springside.modules.orm.hibernate.Page;
import com.skycity.office.bean.DictCode;
import com.skycity.office.bean.DictType;
import com.skycity.office.service.impl.DictCodeServiceImpl;
import com.skycity.office.util.Constants;
import com.skycity.office.web.struts2.CRUDActionSupport;
@ParentPackage("default")
@Results({
@Result(name=CRUDActionSupport.SUCCESS, value="/list", type=ServletActionRedirectResult.class)
})
public class DictCodeAction extends CRUDActionSupport<DictCode>{
?private static final long serialVersionUID = 1L;
?@Autowired
?private DictCodeServiceImpl dictCodeService;
?private String id;
?private DictCode entity;
?private List<DictType> allDictTypes;
?
?private Page<DictCode> page = new Page<DictCode>(Constants.DEFAULT_PAGE_SIZE, true);
?@Override
?public String delete() throws Exception {
??dictCodeService.deleteDictCode(id);
??return RELOAD;
?}
?
?@Override
?public String edit() throws Exception {
??allDictTypes = dictCodeService.getAllDictTypes();
??return INPUT;
?}
?@Override
?public String list() throws Exception {
??page=dictCodeService.getAllDictCodes(page);
??return SUCCESS;
?}
?
?public String show() throws Exception{
??return SHOW;
?}
?@Override
?public String save() throws Exception {
??if (null!=id && !"".equals(id)){
???dictCodeService.updateDictCode(entity);
??}else{
???dictCodeService.saveDictCode(entity);
??}
??return RELOAD;
?}
?
?public void prepare() throws Exception {
??if (null!=id && !"".equals(id)) {
???entity = dictCodeService.getDictCode(id);
??} else {
???entity = new DictCode();
??}
?}
?public DictCode getModel() {
??return entity;
?}
?public Page<DictCode> getPage() {
??return page;
?}
?public String getId() {
??return id;
?}
?public void setId(String id) {
??this.id = id;
?}
?public DictCode getEntity() {
??return entity;
?}
?public void setEntity(DictCode entity) {
??this.entity = entity;
?}
?public List<DictType> getAllDictTypes() {
??return allDictTypes;
?}
}
?
?@Transactional(readOnly=false)
?public void saveDictCode(DictCode authorities) {
??this.dictCodeDAO.save(authorities);
?}
?
?@Transactional(readOnly=false)
?public void updateDictCode(DictCode entity) throws HibernateException, SQLException {
??Session session=this.dictCodeDAO.getSession();
??session.clear();
??session.update(entity);
??
?}
?
?@Transactional(readOnly=false)
?public void deleteDictCode(String id) {
??this.dictCodeDAO.delete(id);
?}
}
因為我采用的sturts2.5+hibernate3.2所有的都支持JPA.所以都用的是JPA注釋,沒有其他servcie,action.dao,struts配置的xml文件.
后來
@Transactional(readOnly=false)
?public void updateDictCode(DictCode entity) throws HibernateException, SQLException {
??Session session=this.dictCodeDAO.getSession();
??session.clear();
??session.update(entity);
??
?}
先對entity進行清空,然后在保存
預計原因.當我想改變某一個字典信息時,講該字典信息和字典類別信息取出來,持久化了,想修改的時候無法修改.所以先clear()再存入.
在update前clear()一下.成功解決該問題
Lyyb2001