精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | ||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
一、问题特征如下: 我是用saveupdate(instance)来保存数据的,但是发现刚创建的时候保存对象没有问题,保存后马上接着修改也没有问题。
使用merge,saveupdate,save,update等方法,都出现几乎同样的错误。让我头都大了,网上查资料,说这类的错误出现的几率少,没搜到更详细的错误报告。我一一排查,把关联映射、生产环境等去掉重来,排查到最后才发现,新建并修改不出问题,但是事后指定一个对象修改,却发生上面的错误。估计耗时两三天了吧,我估计是对象状态的问题,但又不知何从下手。。我能力有限,希望各位给些意见。 二、下面给出我的一下代码和测试报告: 1.保存对象含单向多对一关系。 被测试对象test.Child的hbm: <hibernate-mapping> <id name="id" column="ChildId" type="integer"> <property name="name" type="string"> 2.被关联对象test.Parent如下hbm:
package test; import net.xerllent.system.web.BasePage; private Child child; public void setChild(Child child) { public void setChildDAO(ChildDAO childDAO) { public String persist() { public String refresh() { public String replicate() { public String save() { public String saveOrUpdate() { public String update() { public Map getDictParents(){ 4.Spring2-Hibernate3的merge,persist,refresh,replicate,save,saveOrUpdate,update方法测试表
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
上面代码乱了,再附上:
1.保存对象含单向多对一关系。 被测试对象test.Child的hbm: <hibernate-mapping> <class name="test.Child" table="app_child" schema="dbo"> <id name="id" column="ChildId" type="integer"> <generator class="identity"></generator> </id> <property name="name" type="string"> <column name="name" length="50" not-null="true"></column> </property> <many-to-one name="parent" class="test.Parent" column="ParentID" outer-join="true" update="true"> </many-to-one> <many-to-one name="parentb" class="test.Parentb" column="codea" outer-join="true"> </many-to-one> </class> </hibernate-mapping> 2.被关联对象test.Parent如下hbm: <hibernate-mapping> <class name="test.Parent" table="app_parent" schema="dbo"> <id name="id" column="ParentId" type="integer"><generator class="identity"></generator></id> <property name="name" type="string"> <column name="name" length="50" not-null="true" unique="true"></column> </property> <!-- <set name="children" inverse="false"> <key column="ParentID"/> <one-to-many class="test.Child"/> </set> --> </class> </hibernate-mapping> 3.操作页面jsf。Backingbean如下: package test; import net.xerllent.system.web.BasePage; import org.springframework.dao.DataAccessException; import java.util.Map; public class TestForm extends BasePage { private Child child; private ChildDAO childDAO; public Child getChild() { if(child==null){ // child=(Child)childDAO.getChild(new Integer(3)); child=(Child)childDAO.loadChild(new Integer(3)); if(child==null) { child=new Child(); } } return child; } public void setChild(Child child) { this.child = child; } public void setChildDAO(ChildDAO childDAO) { this.childDAO = childDAO; } public String merge() { try { childDAO.merge(child); return "success"; } catch (RuntimeException e) { return "success"; } } public String persist() { try { childDAO.persist(child); return "success"; } catch (RuntimeException e) { return "success"; } } public String refresh() { try { childDAO.refresh(child); return "success"; } catch (RuntimeException e) { return "success"; } } public String replicate() { try { childDAO.replicate(child); return "success"; } catch (RuntimeException e) { return "success"; } } public String save() { try { childDAO.save(child); return "success"; } catch (RuntimeException e) { return "success"; } } public String saveOrUpdate() { try { childDAO.saveOrUpdate(child); return "success"; } catch (RuntimeException e) { return "success"; } } public String update() { try { childDAO.update(child); return "success"; } catch (RuntimeException e) { return "success"; } } public Map getDictParents(){ return childDAO.getParentsMapList(); } public Map getDictParentbs(){ return childDAO.getParentbsMapList(); } } |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
建议把如何设置Child实例的parent属性的代码也贴出来
|
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
jsf页面代码如下:(提示我的spring OpenSessionInViewFilter是打开的)
<%@taglib uri="http://www.xerllent.cn/donuts" prefix="xer"%> <%@ page language="java" pageEncoding="GB18030"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; //FacesContext ctx=FacesContext.getCurrentInstance(); //ChildDAO cdao=(ChildDAO)ctx.getApplication().getVariableResolver().resolveVariable(ctx,"ChildDAO"); //cdao.addRole(); //cdao.testdelete(); %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSF 'testParentChild.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <f:view> This is my JSF JSP page. <br> <h:form> <h:messages showSummary="true"></h:messages> <h:inputHidden value="#{TestForm.child.id}"></h:inputHidden> <h:panelGrid columns="3"> <t:outputLabel for="name" value="名称"></t:outputLabel> <h:inputText id="name" value="#{TestForm.child.name}" required="true"></h:inputText> <h:message for="name"></h:message> <t:outputLabel for="parent" value="父系统:"></t:outputLabel> <t:selectOneMenu id="parent" value="#{TestForm.child.parent.id}" required="true"> <f:selectItems value="#{TestForm.dictParents}"/> </t:selectOneMenu> <h:message for="parent"></h:message> <t:outputLabel for="parentb" value="父系统b:"></t:outputLabel> <t:selectOneMenu id="parentb" value="#{TestForm.child.parentb.code}" required="true"> <f:selectItems value="#{TestForm.dictParentbs}"/> </t:selectOneMenu> <h:message for="parentb"></h:message> <h:commandButton action="#{TestForm.merge}" value="merge" type="submit"/> <h:commandButton action="#{TestForm.persist}" value="persist" type="submit"/> <h:commandButton action="#{TestForm.refresh}" value="refresh" type="submit"/> <h:commandButton action="#{TestForm.replicate}" value="replicate" type="submit"/> <h:commandButton action="#{TestForm.save}" value="save" type="submit"/> <h:commandButton action="#{TestForm.saveOrUpdate}" value="saveOrUpdate" type="submit"/> <h:commandButton action="#{TestForm.update}" value="update" type="submit"/> </h:panelGrid> </h:form> </f:view> </body> </html> manager bean 如下: package test; import java.sql.SQLException; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.HibernateException; import org.hibernate.Session; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class ChildDAOImp extends HibernateDaoSupport implements ChildDAO { private static final Log log = LogFactory.getLog(Child.class); /* (non-Javadoc) * @see test.ChildDAO#getChild(java.lang.Integer) */ public Child getChild(Integer id){ return (Child)getHibernateTemplate().get(test.Child.class, id); } /* (non-Javadoc) * @see test.ChildDAO#loadChild(java.lang.Integer) */ public Child loadChild(Integer id){ return (Child)getHibernateTemplate().load(test.Child.class, id); } /* (non-Javadoc) * @see test.ChildDAO#getAllParents() */ public List getAllParents(){ try { String queryString = "from Parent"; return getHibernateTemplate().find(queryString); } catch (RuntimeException re) { log.error("find all failed", re); throw re; } } /* (non-Javadoc) * @see test.ChildDAO#getAllParents() */ public List getAllParentbs(){ try { String queryString = "from Parentb"; return getHibernateTemplate().find(queryString); } catch (RuntimeException re) { log.error("find all failed", re); throw re; } } /* (non-Javadoc) * @see test.ChildDAO#getParentsMapList() */ public Map getParentsMapList(){ Map options=new LinkedHashMap(); options.put("请选择..", ""); List parents= getAllParents(); for (Iterator it = parents.iterator(); it.hasNext();) { Parent option = (Parent) it.next(); options.put(option.getName(), option.getId().toString()); } return options; } /* (non-Javadoc) * @see test.ChildDAO#getParentsMapList() */ public Map getParentbsMapList(){ Map options=new LinkedHashMap(); options.put("请选择..", ""); List parents= getAllParentbs(); for (Iterator it = parents.iterator(); it.hasNext();) { Parentb option = (Parentb) it.next(); options.put(option.getName(), option.getCode()); } return options; } public void saveOrUpdate(Child chd){ getHibernateTemplate().saveOrUpdate(chd); } public void merge(Child chd){ getHibernateTemplate().merge(chd); } public void refresh(Child chd){ getHibernateTemplate().refresh(chd); } public void save(Child chd){ getHibernateTemplate().save(chd); } public void persist(Child chd){ getHibernateTemplate().persist(chd); } public void update(Child chd){ getHibernateTemplate().update(chd); } public void replicate(Child chd){ getHibernateTemplate().replicate(chd, org.hibernate.ReplicationMode.OVERWRITE); } } |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
movingboy 写道 建议把如何设置Child实例的parent属性的代码也贴出来
我设置Child实例的parent属性时,根据jsf默认的<h:selectOneMenu>的特性,只对parent的id属性设置了值,其他值都为空。 但是为什么新建后马上接着修改没问题,而事后从数据库指定一个记录对象修改的时候却出错呢? |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
较完整错误消息:
[donuts] DEBUG [http-8080-2] HibernateTransactionManager.handleExistingTransaction(444) | Participating in existing transaction [donuts] DEBUG [http-8080-2] TransactionInterceptor.prepareTransactionInfo(282) | Getting transaction for [test.ChildDAO.update] [donuts] DEBUG [http-8080-2] TransactionSynchronizationManager.getResource(140) | Retrieved value [org.springframework.orm.hibernate3.SessionHolder@204443] for key [org.hibernate.impl.SessionFactoryImpl@f61227] bound to thread [http-8080-2] [donuts] DEBUG [http-8080-2] TransactionSynchronizationManager.getResource(140) | Retrieved value [org.springframework.orm.hibernate3.SessionHolder@204443] for key [org.hibernate.impl.SessionFactoryImpl@f61227] bound to thread [http-8080-2] [donuts] DEBUG [http-8080-2] HibernateTemplate.execute(364) | Found thread-bound Session for HibernateTemplate [donuts] DEBUG [http-8080-2] HibernateTemplate.execute(388) | Not closing pre-bound Hibernate Session after HibernateTemplate [donuts] DEBUG [http-8080-2] TransactionInterceptor.commitTransactionAfterReturning(312) | Completing transaction for [test.ChildDAO.update] [donuts] DEBUG [http-8080-2] TransactionInterceptor.commitTransactionAfterReturning(312) | Completing transaction for [test.ChildDAO.update] [donuts] DEBUG [http-8080-2] HibernateTransactionManager.triggerBeforeCommit(833) | Triggering beforeCommit synchronization [donuts] DEBUG [http-8080-2] HibernateTransactionManager.triggerBeforeCompletion(846) | Triggering beforeCompletion synchronization [donuts] DEBUG [http-8080-2] HibernateTransactionManager.processCommit(660) | Initiating transaction commit [donuts] DEBUG [http-8080-2] HibernateTransactionManager.doCommit(571) | Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@1077c9d] [donuts] DEBUG [http-8080-2] JDBCTransaction.commit(103) | commit [donuts] DEBUG [http-8080-2] AbstractFlushingEventListener.prepareEntityFlushes(111) | processing flush-time cascades [donuts] DEBUG [http-8080-2] AbstractFlushingEventListener.prepareCollectionFlushes(154) | dirty checking collections [donuts] DEBUG [http-8080-2] HibernateTransactionManager.doRollbackOnCommitException(801) | Initiating transaction rollback after commit exception org.springframework.orm.hibernate3.HibernateSystemException: identifier of an instance of test.Parent was altered from 1 to 2; nested exception is org.hibernate.HibernateException: identifier of an instance of test.Parent was altered from 1 to 2 Caused by: org.hibernate.HibernateException: identifier of an instance of test.Parent was altered from 1 to 2 at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:58) at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:157) at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:113) at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196) at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:575) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:662) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:314) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy10.update(Unknown Source) at test.TestForm.update(TestForm.java:89) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.apache.el.parser.AstValue.invoke(AstValue.java:131) at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276) at org.apache.jasper.el.JspMethodExpression.invoke(JspMethodExpression.java:68) at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:77) at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:54) at javax.faces.component.UICommand.broadcast(UICommand.java:383) at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:447) at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:752) at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:97) at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:147) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261) at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:852) at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:584) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1508) at java.lang.Thread.run(Unknown Source) [donuts] DEBUG [http-8080-2] HibernateTransactionManager.doRollback(590) | Rolling back Hibernate transaction on Session [org.hibernate.impl.SessionImpl@1077c9d] [donuts] DEBUG [http-8080-2] JDBCTransaction.rollback(152) | rollback [donuts] DEBUG [http-8080-2] JDBCTransaction.toggleAutoCommit(193) | re-enabling autocommit [donuts] DEBUG [http-8080-2] JDBCTransaction.rollback(163) | rolled back JDBC Connection [donuts] DEBUG [http-8080-2] ConnectionManager.afterTransaction(302) | transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! [donuts] DEBUG [http-8080-2] HibernateTransactionManager.triggerAfterCompletion(875) | Triggering afterCompletion synchronization [donuts] DEBUG [http-8080-2] TransactionSynchronizationManager.clearSynchronization(276) | Clearing transaction synchronization [donuts] DEBUG [http-8080-2] TransactionSynchronizationManager.unbindResource(193) | Removed value [org.springframework.jdbc.datasource.ConnectionHolder@19747c9] for key [org.apache.commons.dbcp.BasicDataSource@190690e] from thread [http-8080-2] [donuts] DEBUG [http-8080-2] HibernateTransactionManager.doCleanupAfterCompletion(657) | Not closing pre-bound Hibernate Session [org.hibernate.impl.SessionImpl@1077c9d] after transaction [donuts] DEBUG [http-8080-2] SessionImpl.disconnect(374) | disconnecting session [donuts] DEBUG [http-8080-2] ConnectionManager.closeConnection(441) | releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] [donuts] DEBUG [http-8080-2] ConnectionManager.afterTransaction(302) | transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! [donuts] DEBUG [http-8080-2] DelegatingVariableResolver.resolveVariable(106) | Attempting to resolve variable 'TestForm' in via original VariableResolver |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
不能修改持久化对象的id值
|
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
janh 写道 不能修改持久化对象的id值
非常感谢!你这句话说到我心坎上去了,但我要修改这个对象的关联值,但如何实现呢? 我这样想,难道被修改的对象的子对象在jsf里都不能直接赋值,必须另在backingbean里先设置个该子对象的Id变量,接受到更改后的Id值后再实例化二级对象,然后再关联!!!这也太麻烦了吧。 或者我怎么先去掉持久化状态呢?,再修改之。就像我新建这个对象后马上接着修改并能正确保存的这个状态。 用这句话可以解决问题吗? /* (non-Javadoc) * @see net.xerllent.system.dao.imp.BaseDao#attachClean(java.lang.Object) */ public void attachClean(Object instance) { log.debug("attaching clean Object instance"); try { getHibernateTemplate().lock(instance, LockMode.NONE); log.debug("attach successful"); } catch (RuntimeException re) { log.error("attach failed", re); throw re; } } |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
janh 写道 不能修改持久化对象的id值
我在getChild()里加了个attachClean方法,但错误依旧!! public Child getChild() { if(child==null){ child=(Child)childDAO.getChild(new Integer(4)); // child=(Child)childDAO.loadChild(new Integer(3)); if(child==null) { child=new Child(); } childDAO.attachClean(child); childDAO.attachClean(child.getParent()); childDAO.attachClean(child.getParentb()); } return child; } |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||
发表时间:2007-08-15
修改对象应该在持久化对象的基础上进行修改。
根据id,get获取到对应的持久化对象,再设置要改变的属性值。 关联对象也同样,根据父id,get获取到anotherParent,再child.setParent(anotherParent); |
|||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||