2010-07-22 12 views
8

मैं विकेट, स्प्रिंग और हाइबरनेट के साथ एक वेब एप्लिकेशन पर काम कर रहा हूं और मुझे रिकॉर्ड अपडेट करने में समस्या आई है। मैंने सत्यापित किया है कि saveOrUpdate विधि लागू की जाती है, और डोमेन ऑब्जेक्ट में डेटा बदल गया है। हालांकि SQL-आउटपुट प्रदर्शित नहीं करता है कि डेटाबेस में कोई भी परिवर्तन किया गया है (उदाहरण में अद्यतन) और प्रभावित रिकॉर्ड अद्यतन नहीं किया गया है।हाइबरनेट रिकॉर्ड अपडेट नहीं कर रहा है - विकेट

मुझे लगता है कि यह अपडेट() का उपयोग करने के लिए और अधिक समझ में आता है, लेकिन मैं saveOrUpdate() नए रिकॉर्ड बनाने में कामयाब रहता है, लेकिन यह उन्हें अपडेट नहीं करता है। मैंने सत्यापित किया है कि इस विधि को लागू किया गया है, और पास किए गए UserVO में अद्यतन फ़ील्ड हैं। यहाँ डीएओ विधि है:

 
jdbc.driver=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost/skuldweb_dev;AUTO=MULTI;CURSOR=READONLY 
jdbc.username= 
jdbc.password= 
hibernate.dialect=org.hibernate.dialect.MySQLDialect 
hibernate.show_sql=true 
hibernate.use_outer_join=true
hibernate.cache.use_query_cache=true hibernate.cache.use_second_level_cache=true hibernate.cache.provider=org.hibernate.cache.HashtableCacheProvider
hibernate.schemaUpdate=true

यहाँ applicationContext.xml में sessionFactory सेम है::

 
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource"/> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
       <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
       <prop key="use_outer_join">${hibernate.use_outer_join}</prop> 
       <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop> 
       <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop> 
       <prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop> 
       <prop key="hibernate.connection.pool_size">10</prop> 
       <prop key="hibernate.connection.autocommit">true</prop> 
       <prop key="hibernate.jdbc.batch_size">1000</prop> 
       <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop> 
      </props> 
     </property> 
     
     <property name="annotatedClasses"> 
      <list> 
       <value>com.upbeat.app.skuldweb.domain.UserVO</value> 
       <value>com.upbeat.app.skuldweb.domain.UserLevelVO</value>
</list> </property> <property name="schemaUpdate" value="${hibernate.schemaUpdate}"/> </bean>

Hopefully one of you can help me out.

Updated Here's some info from the log (onSubmit() sets off these entries in the log -- the last entry should be when the request is being redirected to another page (after the record should have been updated).

 

[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:239): Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter 
[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:214): Returning cached instance of singleton bean 'sessionFactory' 
[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:181): Opening single Hibernate Session in OpenSessionInViewFilter 
[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:318): Opening Hibernate Session 
[DEBUG] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.(SessionImpl.java:247): opened session at timestamp: 5242215490777088 
[TRACE] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.setFlushMode(SessionImpl.java:1316): setting flush mode to: NEVER 
[DEBUG] 2010-07-23 00:29:26,305 :org.apache.wicket.Session.getPage(Session.java:700): Getting page [path = 4:userprofile_form, versionNumber = 0] 
[DEBUG] 2010-07-23 00:29:26,306 :org.apache.wicket.markup.html.form.persistence.CookieValuePersister.getCookie(CookieValuePersister.java:210): Unable to find Cookie with name=userprofile_form.email and request URI=/upbeat-app-skuld-web/ 
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.engine.IdentifierValue.isUnsaved(IdentifierValue.java:127): id unsaved-value: 0 
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:546): detached instance of: com.upbeat.app.skuldweb.domain.UserVO 
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:228): updating detached instance 
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:295): updating [com.upbeat.app.skuldweb.domain.UserVO#1] 
[TRACE] 2010-07-23 00:29:26,310 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:346): updating [com.upbeat.app.skuldweb.domain.UserVO#1] 
[TRACE] 2010-07-23 00:29:26,311 :org.hibernate.engine.Cascade.cascade(Cascade.java:138): processing cascade ACTION_SAVE_UPDATE for: com.upbeat.app.skuldweb.domain.UserVO 
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:239): cascading to saveOrUpdate: com.upbeat.app.skuldweb.domain.UserLevelVO 
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.engine.IdentifierValue.isUnsaved(IdentifierValue.java:127): id unsaved-value: 0 
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:546): detached instance of: com.upbeat.app.skuldweb.domain.UserLevelVO 
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:228): updating detached instance 
[TRACE] 2010-07-23 00:29:26,313 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:295): updating [com.upbeat.app.skuldweb.domain.UserLevelVO#1] 
[TRACE] 2010-07-23 00:29:26,313 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:346): updating [com.upbeat.app.skuldweb.domain.UserLevelVO#1] 
[TRACE] 2010-07-23 00:29:26,313 :org.hibernate.engine.Cascade.cascade(Cascade.java:173): done processing cascade ACTION_SAVE_UPDATE for: com.upbeat.app.skuldweb.domain.UserVO 
[DEBUG] 2010-07-23 00:29:26,314 :org.apache.wicket.RequestCycle.setRequestTarget(RequestCycle.java:644): replacing request target org.apache.wicket.r[email protected]676067951[Page class = com.upbeat.app.skuldweb.web.user.UserProfilePage, id = 4, version = 0]->userprofile_form->interface org.apache.wicket.markup.html.form.IFormSubmitListener.IFormSubmitListener (request paramaters: [RequestParameters componentPath=4:userprofile_form pageMapName=null versionNumber=0 interfaceName=IFormSubmitListener componentId=null behaviorId=null urlDepth=-1 parameters={[email protected],userprofile__form2_hf_0=} onlyProcessIfPathActive=false]) with [[email protected] pageClass=com.upbeat.app.skuldweb.web.user.UserProfilePage] 

Update 2 Here's the UserVO without the getters/setters

 
@Entity 
@Table(name = "USERS") 
@NamedQueries({ 
    @NamedQuery(name = "user.getById", query = "from UserVO item where item.id = :id"), 
    @NamedQuery(name = "user.getAllUsers", query = "from UserVO item order by item.registerDate desc"), 
    @NamedQuery(name = "user.countAll", query = "select count(item) from UserVO item"), 
    @NamedQuery(name = "user.getByUsername", query = "from UserVO item where item.username = :username"), 
    @NamedQuery(name = "user.authenticate", query = "from UserVO item where item.username = :username AND item.passwordHash = :passwordHash") 
}) 
public class UserVO extends BaseVO {

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "ID") 
protected long id; 

@OneToOne(cascade = CascadeType.ALL) 
protected UserLevelVO userLevelVO; 

@Basic 
@Column(name = "USERNAME") 
protected String username; 

@Basic 
@Column(name = "PASSWORD_HASH") 
protected String passwordHash; 

@Basic 
@Column(name = "EMAIL") 
protected String email; 

@Temporal(TemporalType.TIMESTAMP) 
@Column(name = "REGISTER_DATE") 
protected Date registerDate; 

@Temporal(TemporalType.TIMESTAMP) 
@Column(name = "LAST_LOGIN_DATE") 
protected Date lastLoginDate; 

}

उत्तर

25

हाइबरनेट अक्सर अद्यतन defers जब तक सत्र प्लावित है

 
public class SkuldwebDAOImpl extends HibernateDaoSupport implements SkuldwebDAO { 
    public void updateUser(UserVO userVO) { 
     getSession().saveOrUpdate(userVO); 
    } 
} 

यहाँ मेरी संपत्ति फ़ाइल है। यह जांचने के लिए कि क्या आपके मामले में यह समस्या है, अपने अपडेट स्टेटमेंट के बाद getSession().flush() डालें।

आप लेनदेन का प्रबंधन कैसे करते हैं? सत्र प्रतिबद्ध होने पर फ़्लशिंग स्वचालित रूप से हो जाएगी, लेकिन यदि आपके पास एक दोषपूर्ण लेनदेन कॉन्फ़िगरेशन है, तो आप जेडीबीसी कनेक्शन को समाप्त कर सकते हैं लेकिन हाइबरनेट सत्र से जुड़े लेनदेन को नहीं कर सकते हैं।

संपादित करें: अपने अद्यतन के आधार पर, मुझे लगता है कि FlushMode कभी कुछ पंक्ति में करने के लिए सेट है:

[TRACE] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.setFlushMode(SessionImpl.java:1316): setting flush mode to: NEVER 

मुझे लगता है इस समस्या है। यह सत्र को स्वचालित रूप से कभी भी फ्लश करने का कारण नहीं बनता है - आमतौर पर जो आप केवल पढ़ने के लिए लेनदेन में करना चाहते हैं, न कि जब आप डेटा संशोधित करते हैं। ऐसा लगता है कि आप लेन-देन के बिना चल रहे हैं (ऑटोकॉमिट सही पर सेट है - जिसकी तरह से अनुशंसा नहीं की जाती है)। OpenSessionInViewFilter के लिए जावाडोक कुछ सुराग प्रदान करता है:

इस फिल्टर डिफ़ॉल्ट रूप से फ्लश FlushMode.NEVER करने के लिए सेट मोड के साथ हाइबरनेट सत्र फ्लश नहीं लिया जाएगा। यह सेवा परत लेनदेन के संयोजन में उपयोग किया जाता है जो फ़्लशिंग की देखभाल करता है: सक्रिय लेनदेन प्रबंधक फ़्लश मोड को फ़्लश मोड में अस्थायी रूप से फ्लैश मोड में बदल देगा। फ्लू मोड को फ्लश मोड में रीसेट करें। अंत में फ्लश मोड रीसेट करें प्रत्येक लेनदेन का। यदि आप लेनदेन के बिना इस फ़िल्टर का उपयोग करना चाहते हैं, तो डिफ़ॉल्ट फ्लश मोड को बदलने पर विचार करें ("flushMode" संपत्ति के माध्यम से)।

दूसरे शब्दों में, आप दो विकल्प हैं: या तो ऑटो के लिए अपने OpenSessionInViewFilter पर सेट flushMode, या, इस तरह के HibernateTransactionManager के रूप में एक सौदे के प्रबंधक autocommit बंद कर देते हैं और कॉन्फ़िगर करें।

+0

हां, अच्छा पकड़ +1 –

+0

आपको बहुत बहुत धन्यवाद! GetSession()। Flush() को अद्यतन विधि में जोड़ना काम किया। मैंने OpenSessionInViewFilter में फ्लशमोड को "ऑटो" पर सेट करने का प्रयास किया था, लेकिन मुझे अभी भी अद्यतन चलाने के लिए getSession() फ्लश() को मैन्युअल रूप से आमंत्रित करना था (autocommitt चालू और बंद के साथ)। – John

+0

फ्लशमोड ऑटो पर सेट किया गया है और ऑटोोकॉमिट अक्षम कर रहा है, मैं इसे करने के द्वारा काम करने में सक्षम था; लेनदेन tr = getSession()। StartTransaction(); । GetSession() अद्यतन (VO); tr.commit() ;. एक बार फिर धन्यवाद – John

6

चूंकि आप स्प्रिंग का उपयोग कर रहे हैं, इसलिए मैं अनुशंसा करता हूं कि आप अपने लेन-देन को प्रबंधित करने के लिए स्प्रिंग के प्लेटफार्म ट्रांज़ेक्शन मैनेजर का उपयोग करें। लेनदेन प्रबंधन के हिस्से के रूप में वसंत स्वचालित रूप से सत्र को फ्लश करता है। इसका मतलब है कि आपको अपने कोड में इनमें से किसी भी पहलू के बारे में चिंता करने की ज़रूरत नहीं है।

वसंत में एक ओपनसेशन इनव्यूफिल्टर है जो लेनदेन प्रबंधक को सत्र शुरू/फ्लश करने के लिए हुक करता है और आप स्प्रिंग के @ ट्रांसेक्शनल के साथ अपने तरीकों को एनोटेट कर सकते हैं ताकि यह इंगित किया जा सके कि आप किसी विशेष विधि के लिए 'लिखना' लेनदेन चाहते हैं। यह आपके रिकॉर्ड अपडेट करना चाहिए।

संबंधित मुद्दे