org.hibernate.StaleStateException: Batch update returned unexpected row count

來源:互聯網
上載者:User

轉自http://hi.baidu.com/besun/blog/item/01973ff7a9ce0929730eec38.html

1、a different object with the same identifier value was already associated with the session。   錯誤原因:在hibernate中同一個session裡面有了兩個相同標識但是是不同實體。   解決方案一:session.clean()   PS:如果在clean操作後面又進行了saveOrUpdate(object)等改變資料狀態的操作,有可能會報出"Found two representations of same collection"異常。   解決方案二:session.refresh(object)   PS:當object不是資料庫中已有資料的對象的時候,不能使用session.refresh(object)因為該方法是從 hibernate的session中去重新取object,如果session中沒有這個對象,則會報錯所以當你使用saveOrUpdate (object)之前還需要判斷一下。   解決方案三:session.merge(object)   PS:Hibernate裡面內建的方法,推薦使用。 2、Found two representations of same collection   錯誤原因:見1。   解決方案:session.merge(object) 以上兩中異常經常出現在一對多映射和多對多映射中。 3、net.sf.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: BBusinessman

從這個bug的字面上,應該是BBusinessman的某個屬性是一個實體,在這個實體沒有儲存之前就儲存Businessman對象,導致的錯誤。所以我就一直看Businessman的屬性中到底哪個是實體,結果發現三個,分別City , Type, Status,而且這三個實體都是dao.load( Id , Session)從資料庫中獲得的,不是已經有Id的,或者是null,而不存在沒有儲存的實體。

於是我又懷疑,是否是同一個事務需要一個session,如果不使用此session,是不是這個原因,於是我把事務中方法裡所有dao.getSession()這樣不太明確的地方都是用方法傳入的session,這樣session都是同一個了,但是仍舊有此錯誤。

這樣,BBusinessman的各個屬性都是沒有問題的。那麼是否是沒有儲存BBusinessman之前,而且BBusinessman又被當作某個實體的屬性,首先儲存此實體,然後去儲存BBusinessman,這樣是否會導致這個錯誤。結果我發現,正是這個問題。

================錯誤的寫法:===================

Session session = dao.getSession();

Transaction tx = session.beginTransaction();

Bo.setBman( form ,man,session);

Bo.saveChangeTable( man,session); // 把man當作屬性賦給ChangeTable,並儲存ChangeTable. 就是這出的錯,

dao.save(man,session); // 儲存man

tx.commit();

==================== 應該這樣寫:===============

Session session = dao.getSession();

Transaction tx = session.beginTransaction();

Bo.setBman( form ,man,session);

dao.save(man,session); // 儲存man

Bo.saveChangeTable( man,session); // 把man當作屬性賦給ChangeTable,並儲存ChangeTable. 就是這出的錯,

tx.commit();

這樣,問題就解決了。

4、Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition 錯誤解決

錯誤碼:
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
錯誤原因:
OpenSessionInViewFilter在getSession的時候,會把擷取回來的session的flush mode 設為FlushMode.NEVER。然後把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個過程都使用同一個session,在請求過後再接除該sessionFactory的綁定,最後closeSessionIfNecessary根據該session是否已和transaction綁定來決定是否關閉session。在這個過程中,若HibernateTemplate 發現自當前session有不是readOnly的transaction,就會擷取到FlushMode.AUTO Session,使方法擁有寫入權限。
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉為Flush.AUTO,擁有insert,update,delete操作許可權,如果沒有transaction,並且沒有另外人為地設flush model的話,則doFilter的整個過程都是Flush.NEVER。所以受transaction保護的方法有寫入權限,沒受保護的則沒有。
參考文章:
http://calvin.blog.javascud.org/post/46.htm
解決辦法:
採用spring的事務聲明,使方法受transaction控制
<bean id="baseTransaction"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="proxyTargetClass" value="true"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="userService" parent="baseTransaction">
<property name="target">
<bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
</property>
</bean>

5、關於Hibernate的 Batch update returned unexpected row count from update異常

ERROR [http-8080-Processor22] (BatchingBatcher.java:60) - Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1

1).使用的是hibernate的saveOrUpdate方法儲存執行個體。saveOrUpdate方法要求ID為null時才執行SAVE,在其它情況下執行UPDATE。在儲存執行個體的時候是新增,但你的ID不為null,所以使用的是UPDATE,但是資料庫裡沒有主鍵相關的值,所以出現異常。


=================================================================

異常:
在插入時:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1

解決方案:
如果是自增主鍵?
有的資料庫是可以修改自增主鍵例如:mysql,有的資料庫是不允許修改自增主鍵的例如postgresql
不要設定自增主鍵的值


2)

在Hibernate映射一對多,多對一,多對多的時候新增常常會出現這個異常,代碼如下:

public void saveFunctionCell(FunctionCell functionCell, Integer pid) {
System.out.println("現在進行新增操作");
FunctionCell fc = new FunctionCell();
try {
BeanUtils.copyProperties(fc, functionCell);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
fc.setFuncCellID(null);
// 獲得父許可權
FunctionCell pfc = functionCellDao.findFunctionCellByID(pid);
fc.setParentFunctionCell(pfc);
functionCellDao.saveFunctionCell(fc);
}

注意特別標識出來的這個地方,BeanUtils拷貝Bean屬性的時候,它會將你的Integer類型全部設定成0,在這裡設定一個空,這樣就不會拋出錯誤了。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.