Hibernate的單向Many-to-one關(guān)系問(wèn)題解決
Posted on 2008-12-10 15:41 skycity 閱讀(5212) 評(píng)論(0) 編輯 收藏 所屬分類: Hibernate相關(guān) 、Spring框架我在使用雙向Many-to-one關(guān)系時(shí),想實(shí)現(xiàn)數(shù)據(jù)字典管理,1的一端是數(shù)據(jù)字典類別比如"性別","學(xué)歷",many一端通過(guò)外鍵進(jìn)行引用.
1.單獨(dú)對(duì)1的一端進(jìn)行crud都沒(méi)有問(wèn)題,建好連接以后,刪除1端,many同時(shí)刪除有聯(lián)系的記錄
2.設(shè)置好了表間的聯(lián)系.進(jìn)行CRD沒(méi)啥問(wèn)題.update的時(shí)候,不對(duì)外鍵進(jìn)行任何修改時(shí).正常運(yùn)行.修改外鍵時(shí),報(bào)如下錯(cuò)誤
?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
網(wǎng)上找了很久.有的說(shuō)不是many-to-many的問(wèn)題.很多地方說(shuō)什么merge().saveOrUpdate(),嘗試了很多,網(wǎng)上詳細(xì)的解決方案也沒(méi)有.將修改時(shí)調(diào)用的方法注釋了,還是會(huì)出現(xiàn)這種錯(cuò)誤.有點(diǎn)崩潰的感覺(jué)
試了merge().這里提到merge()也碰到一個(gè)奇怪的問(wèn)題.merge按正常來(lái)說(shuō)應(yīng)該是合并的意思.我在many端修改時(shí).使用了merge,居然one端進(jìn)行了修改
比如.我想將"性別"為"女"的類型改成"學(xué)歷"(當(dāng)然這是我測(cè)試),他最后修改了我的字典類別表,將"性別"類別改成了"學(xué)歷"類別.不知道是什么原因.
貼出我的部分代碼:
字典類別表的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實(shí)現(xiàn)
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);
?}
}
因?yàn)槲也捎玫膕turts2.5+hibernate3.2所有的都支持JPA.所以都用的是JPA注釋,沒(méi)有其他servcie,action.dao,struts配置的xml文件.
后來(lái)
@Transactional(readOnly=false)
?public void updateDictCode(DictCode entity) throws HibernateException, SQLException {
??Session session=this.dictCodeDAO.getSession();
??session.clear();
??session.update(entity);
??
?}
先對(duì)entity進(jìn)行清空,然后在保存
預(yù)計(jì)原因.當(dāng)我想改變某一個(gè)字典信息時(shí),講該字典信息和字典類別信息取出來(lái),持久化了,想修改的時(shí)候無(wú)法修改.所以先clear()再存入.
在update前clear()一下.成功解決該問(wèn)題
Lyyb2001