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

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

你可能感兴趣的:(bean,Hibernate,orm,jpa,Office)