Hibernate的单向Many-to-one关系问题解决

我在使用双向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()一下.成功解决该问题



欢迎大家访问我的个人网站 萌萌的IT人

你可能感兴趣的:(Hibernate的单向Many-to-one关系问题解决)