在搭建一個spring3.0+hibernate+jpa項目架構,根據網友提供的例子,在junit下做了一個存儲資料的測試,報如下異常:
org.springframework.transaction.transactionsystemexception: could not commit jpa transaction; nested exception is javax.persistence.rollbackexception: error while commiting the transaction
at org.springframework.orm.jpa.jpatransactionmanager.docommit(jpatransactionmanager.java:476)
at org.springframework.transaction.support.abstractplatformtransactionmanager.processcommit(abstractplatformtransactionmanager.java:754)
at org.springframework.transaction.support.abstractplatformtransactionmanager.commit(abstractplatformtransactionmanager.java:723)
at org.springframework.transaction.interceptor.transactionaspectsupport.committransactionafterreturning(transactionaspectsupport.java:394)
at org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:117)
at org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172)
at org.springframework.aop.framework.cglib2aopproxy$dynamicadvisedinterceptor.intercept(cglib2aopproxy.java:625)
at com.alcor.test.service.testaservice$$enhancerbycglib$$41631835.add(<generated>)
at com.alcor.test.junit.testunit.testtransaction(testunit.java:36)
at sun.reflect.nativemethodaccessorimpl.invoke0(native method)
at sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:57)
at sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43)
at java.lang.reflect.method.invoke(method.java:601)
at junit.framework.testcase.runtest(testcase.java:168)
at junit.framework.testcase.runbare(testcase.java:134)
at junit.framework.testresult$1.protect(testresult.java:110)
at junit.framework.testresult.runprotected(testresult.java:128)
at junit.framework.testresult.run(testresult.java:113)
at junit.framework.testcase.run(testcase.java:124)
at junit.framework.testsuite.runtest(testsuite.java:232)
at junit.framework.testsuite.run(testsuite.java:227)
at org.junit.internal.runners.junit38classrunner.run(junit38classrunner.java:81)
at org.eclipse.jdt.internal.junit4.runner.junit4testreference.run(junit4testreference.java:50)
at org.eclipse.jdt.internal.junit.runner.testexecution.run(testexecution.java:38)
at org.eclipse.jdt.internal.junit.runner.remotetestrunner.runtests(remotetestrunner.java:467)
at org.eclipse.jdt.internal.junit.runner.remotetestrunner.runtests(remotetestrunner.java:683)
at org.eclipse.jdt.internal.junit.runner.remotetestrunner.run(remotetestrunner.java:390)
at org.eclipse.jdt.internal.junit.runner.remotetestrunner.main(remotetestrunner.java:197)
caused by: javax.persistence.rollbackexception: error while commiting the transaction
at org.hibernate.ejb.transactionimpl.commit(transactionimpl.java:71)
at org.springframework.orm.jpa.jpatransactionmanager.docommit(jpatransactionmanager.java:467)
... 27 more
caused by: org.hibernate.exception.sqlgrammarexception: could not execute jdbc batch update
at org.hibernate.exception.sqlstateconverter.convert(sqlstateconverter.java:90)
at org.hibernate.exception.jdbcexceptionhelper.convert(jdbcexceptionhelper.java:66)
at org.hibernate.jdbc.abstractbatcher.executebatch(abstractbatcher.java:275)
at org.hibernate.engine.actionqueue.executeactions(actionqueue.java:266)
at org.hibernate.engine.actionqueue.executeactions(actionqueue.java:167)
at org.hibernate.event.def.abstractflushingeventlistener.performexecutions(abstractflushingeventlistener.java:321)
at org.hibernate.event.def.defaultflusheventlistener.onflush(defaultflusheventlistener.java:50)
at org.hibernate.impl.sessionimpl.flush(sessionimpl.java:1028)
at org.hibernate.impl.sessionimpl.managedflush(sessionimpl.java:366)
at org.hibernate.transaction.jdbctransaction.commit(jdbctransaction.java:137)
at org.hibernate.ejb.transactionimpl.commit(transactionimpl.java:54)
... 28 more
caused by: java.sql.batchupdateexception: table ‘j2ee.student‘ doesn‘t exist
at com.mysql.jdbc.preparedstatement.executebatchserially(preparedstatement.java:2007)
at com.mysql.jdbc.preparedstatement.executebatch(preparedstatement.java:1443)
at com.mchange.v2.c3p0.impl.newproxypreparedstatement.executebatch(newproxypreparedstatement.java:1723)
at org.hibernate.jdbc.batchingbatcher.doexecutebatch(batchingbatcher.java:70)
at org.hibernate.jdbc.abstractbatcher.executebatch(abstractbatcher.java:268)
... 36 more
網上搜尋了一陣,沒什麼收獲。還是自己解決吧。逐層分析異常堆棧如下:
caused by: java.sql.batchupdateexception: table ‘j2ee.student‘ doesn‘t exist; caused by: org.hibernate.exception.sqlgrammarexception: could not execute jdbc batch update;
caused by: javax.persistence.rollbackexception: error while commiting the transaction;
猜測問題的原因可能是因為:insert一條記錄,正常情況下,如果表不存在,則會建立表,然後insert記錄。這裡因為是junit環境,且表不存在,在一個“事務”環境中,要建表、insert記錄,因為什麼原因,建表失敗。導緻insert失敗。
為了驗證這個測試,手動建表,然後執行該junit測試操作,insert成功;
删除表,在正常環境下啟動web伺服器,成功啟動後表即被建立,然後對該表的操作都成功。
到這裡,初步得出一個結論,jap+hibernate+spring環境,建表同對表的操作不宜在一個“事務”中完成;
以上分析還未找到理論上的答案...