1. 程式人生 > >hibernate+struts+Spring常見異常

hibernate+struts+Spring常見異常

ets 解決方法 hbm.xml Coding resource sig jdbc 現在 靜態

Exception : No form found under ‘loginForm‘ in locale ‘en_US‘

這個錯誤完全是我自己給自己找麻煩,我在給loginForm做表單驗證時,用了validator,我在寫validation.xml文件時,突然發神經,想寫得比較國際化一點,這樣寫的:

<formset language="zh" country="CN"> <!--這個是zh_CN的-->

開始是一點問題都沒有,因為我們大家一般都用中文系統,後來有一天我用linux,當時環境是english,結果發現頁面就報錯:No form found under ‘loginForm‘ in locale ‘en_US‘。

當時,特別郁悶,後來仔細回憶,想起當時只在validation.xml文件裏顯式的寫過國際化相關的東西,後來就把 language="zh" country="CN" 給刪掉了。即:
<formset>。。。。。。</formset>

再用英文系統訪問就沒有事情了,看來你要是想國際化,就把所有的情況的配置都寫全了,不要只指定中文的配置,英文的不配置,那樣,別人用英文系統的人就會出錯。所以,建議還是不要制定國際化,看來有的時候還是偷懶一點比較好!


hibernate,one to many關系時出現:Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column

Hibernate: select max(orders_id) from orders
Hibernate: insert into orders (member_id, orderno, realname, address, zip, tel, payment, email, memo, price, time, tag, orders_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select member0_.member_id as member1_0_, member0_.username as username0_, member0_.password as password0_, member0_.realname as realname0_, member0_.tel as tel0_, member0_.address as address0_, member0_.zip as zip0_, member0_.email as email0_ from member member0_ where member0_.username=?
Hibernate: select orders0_.member_id as member2_1_, orders0_.orders_id as orders1_1_, orders0_.orders_id as orders1_5_0_, orders0_.member_id as member2_5_0_, orders0_.orderno as orderno5_0_, orders0_.realname as realname5_0_, orders0_.address as address5_0_, orders0_.zip as zip5_0_, orders0_.tel as tel5_0_, orders0_.payment as payment5_0_, orders0_.email as email5_0_, orders0_.memo as memo5_0_, orders0_.price as price5_0_, orders0_.time as time5_0_, orders0_.tag as tag5_0_ from orders orders0_ where orders0_.member_id=?
1
Hibernate: update orders set member_id=null where member_id=?
SQL Error: 0, SQLState: 01004
Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column ‘member_id‘ at row 1
Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:202)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at net.yywn.hibernate.database.DbOperate.delete(DbOperate.java:602)
at net.yywn.hibernate.database.DbOperateTest.testOneToMany(DbOperateTest.java:265)
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 junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.sql.BatchUpdateException: Data truncation: Column was set to data type implicit default; NULL supplied for NOT NULL column ‘member_id‘ at row 1
at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:657)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
... 25 more


問題分析:

1(這是該用戶的訂單數)
Hibernate: update orders set member_id=null where member_id=?(開始執行delete該用戶)

這是上面代碼片段的分析:可知,該delete的操作沒事執行,而是先去執行update。由於member_id為null,而

數據庫中相應的字段設置不為null。

問題解決:

當然不能去該數據庫的那個字段(設置為null,那就是緣木求魚了)

細看配置文件,發現member沒配inverse(初始值為false)屬性。

把它設為true即可!

個人認為inverse屬性是用來設置主動權的。在member的set(orders)中設置其為true,表示把主動權交給了

member,這樣刪除member的同時就把member的orders也刪除了。(其實是先刪orders再member)

成功後部分sql如下:

Hibernate: delete from orders where orders_id=?
Hibernate: delete from orders where orders_id=?
Hibernate: delete from member where member_id=?

..................................................................................

Hibernate錯誤:org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1

原因多半是你的mapping文件的主鍵沒有設置對。檢查如下:

一:看你的主鍵類型是什麽?如果是long,int等,記得設置unsaved-value="0"

二:如果是string 的話,請設置unsaved-value="null"

註意unsaved-value是個很重要的屬性。Hibernate通過這個屬性來判斷一個對象應該save還是 update,如果這個對象的id是unsaved-value的話,那說明這個對象不是 persistence object要save(insert);如果id是非unsaved-value的話,那說明這個對象是persistence object(數據庫中已存在),只要update就行了。 你可以Debug跟一下你的代碼,看看在 session.update(obj); 的時候,obj的主鍵的值是不是按你定義的那樣,obj可以被hibernate認為是一個已經持久化在數據庫裏的對象

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

java.lang.NoClassDefFoundError: antlr/ANTLRException

原因是:缺少antlr-2.7.5H3.jar

---------------------------------------2----------------------------------------------

類 java.lang.NoSuchMethodError

java.lang.Object

|

+----java.lang.Throwable

|

+----java.lang.Error

|

+----java.lang.LinkageError

|

+----java.lang.IncompatibleClassChangeError

|

+----java.lang.NoSuchMethodError

public class NoSuchMethodError

extends IncompatibleClassChangeError

如果應用程序試圖調用一個類的指定方法(無論是靜態還是動態),但是該類不再有該方法的定義,則拋出該異常。

通常由編譯器檢測此錯誤;如果類定義不允許再作兼容性的改變,那麽此錯誤只可能發生在運行時刻。

構造子索引

NoSuchMethodError()

NoSuchMethodError(String)

用指定的詳細信息構造 NoSuchMethodException。

構造子

NoSuchMethodError

public NoSuchMethodError()

NoSuchMethodError

public NoSuchMethodError(String s)

用指定的詳細信息構造 NoSuchMethodException。

參數:

s - 詳細信息。

----------------------------------3--------------------------------------------------

今天用hibernate3做關系映射,當調用映射類的時候總是報

org.hibernate.LazyInitializationException: could not initialize proxy錯誤

原因:

hb3對many-to-one的默認處理是lazy = "proxy" 而hb2是false

所以,要這麽設置

<many-to-one name="shop_type" column="sort_id" class="liubi.ShopType"

cascade="all" outer-join="true" lazy="false" />

------------------------------------4--------------------------------------------------

java.sql.Timestamp異常

原因:時間date錯誤

更改時間java.util.Date 為java.lang.String就好了,同時修改配置文件中的內容

------------------------------------5--------------------------------------------------

Cannot find bean in any scope

分類:Struts異常

1.出現這種錯誤一般是資源文件沒找到或是資源文件裏沒有對應的key值。

2.struts-config.xml裏的Action配置裏把redirect設置為了true;改成false,

3.在Action裏一般會request.setAttribute()一些對象,然後在轉向的jsp文件裏

(用tag或 request.getAttribute()方法)得到這些對象並顯示出來。

這個異常是說jsp要得到一個對象,

但前面的Action裏並沒有將對象設置到request(也可以是session、servletContext)裏。

可能是名字錯了,請檢查jsp裏的tag的一般是name屬性,或getAttribute()方法的參數值;

或者是Action邏輯有問題沒有執行setAttribute()方法就先轉向了。

還有另外一個可能,純粹是jsp文件的問題,例如<logic:iterate>會指定一個id值,

然後在循環裏<bean:write>使用這個值作為name的值,如果這兩個值不同,

也會出現此異常。(都是一個道理,request裏沒有對應的對象。)

4.這個情況比較特殊,應該算沒有把STRUTS標記庫的機制搞明白,

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>

如果沒有在頭聲明這個就用logic:iterate標記,

在bean:write的時候就會出異常!

---------------------------------6----------------------------------------------------

HibernateException: Not able to obtain connection

org.hibernate.HibernateException: Not able to obtain connection

差不多等於沒有連接數據庫了。要保證Hibernate的Session工廠能正常工作。

這個一般我們的做法是Session工廠設置成靜態的。

然後需要進行操作就打開一個會話。所以在設計的時候註意一下。這個Session工廠對象。

最好是放在

static{}塊裏。然後用個抽象類去實現它,然後其他的類都實現這個抽象類就搞定了!

---------------------------------7----------------------------------------------------

org.hibernate.MappingException: Error reading resource: XXXX.XML

這個異常出現的報錯還有:

Could not configure datastore from input stream

org.dom4j.DocumentException: xxxxx(系統找不到指定的文件。) Nested exception: xxxx

org.hibernate.MappingException: Error reading resource: xxxx

這個異常主要出現的情況有:

(1)沒有映射文件,也就是沒有xxx.hbm.xml

(2)在xxx.hbm.xml文件中有錯誤,主要可能是書寫錯誤,或有亂碼

(3) 這個問題最惡心,一般人不會註意到,就是要註意配置文件和映射文件都必須用同一個版本的HIBERNATE,怎麽看是否用同一個HIBERNATE呢,你可以查看hibernate.cfg.xml和xxx.hbm.xml開頭內容:

例如

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

如果一個是2.0一個是3.0到時候DOM4J就會出異常。解析不了咯!

---------------------------------------8-----------------------------------------------

save the transient instance before flushing

1.

(1)做Hibernate多對一的時候,報錯:

org.apache.jasper.JasperException: Error creating bean with name ‘sf‘ defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is org.hibernate.PropertyNotFoundException: Could not find a getter for person in class com.accp.vo.Course

因為配置文件中的一個 <many-to-one name="person" ../> 中的person屬性名稱寫錯了.

還有原因如下:

1)getter()方法寫錯了,沒有按照javaBean的規則寫.

2)*.hmb.xml中的屬性名和pojo中的是否一致.註意:屬性名是否多了空格.

(2).Hibernate多對一報錯:

save the transient instance before flushing

具體錯誤為在one-to-many中,對many進行save時,由於沒有加入one的外建,導致錯誤。

具體解決方法:

(1)、在one的hbm文件中 invest=true

(2)、在many保存前務必要求one的存在

---------------------------------------9-----------------------------------------------

Named query not known

在使用session.getNamedQuery("XXX");執行HQL語句的時候,沒有找 XXX語句,這主要是2個原因

1:粗心,把名給寫錯了

2:XXX的HQL語句所在的.hbm.xml沒有在hibernate.cfg.xml裏註冊過!

---------------------------------------10----------------------------------------------

Expected positional parameter count: X, actual parameters:

org.hibernate.QueryException: Expected positional parameter count: 2, actual parameters: [] [SELECT * from Ad where gr_id = ? and adst_id = ?]

這樣的異常主要原因是:

//以下為例子

Query query =session.getNamedQuery("OnlienAd");

query.setParameter(0,gray.getId());

query.setParameter(1,Globals.UPED_STATE);

可以看到query.setParameter()設置了位,也可以理解成他在要執行的HQL語句中占了2個位置。

然後執行的時候會對應HQL裏的?中去。

如果你並沒有setParameter(),但你的HQL裏卻有?那麽就會出這個異常。

---------------------------------------11---------------------------------------------

org.hibernate.MappingException: Association references:XXX

---------------------------------------12---------------------------------------------

org.hibernate.exception.SQLGrammarException: could not initialize

無法實例集合。

這個是問題在你當前的實體中有一個一對多需實例的對象。但這個對象卻無法實例出來,說明一對多那個多的一方實體有問題,多數情況可能有:

1、數據庫該動過但代碼沒動

2、實體代碼有錯誤

---------------------------------------13---------------------------------------------

org.hibernate.id.IdentifierGenerationException

異常信息:org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():

異常原因:

<id>元素配置不正確,

<id>元素缺少其子元素<generator></generator>的配置。

解決方法:<id>元素映射了相應數據庫表的主鍵字段,對其子元素<generator class="">,其中class的取值可以為increment、identity、sequence、hilo、native...... 等,更多的可參考hibernate參考文檔,一般取其值為native 。

MySQL:identity,increment,hilo,native.

SQL Server:identity,increment,hilo,native.

Oracle:sequence,seqhilo,increment,native.

跨平臺開發:native.

native將字段管理交給數據庫自己定義。

---------------------------------------8-----------------------------------------------

not-null property references a null or transient value

此異常出現看開頭就個單詞就知道啦

的實體約束不能為空卻為空造成的,那我在這說一下對於這樣的情況我們時常犯的錯誤。

我們在對實體進行更新操作時最好是在一個會話中將數據從數據庫中調出並實例BEAN的對象。

然後再對此對象進行更改後在更新。

這樣的好處是:

一、數據是最新鮮的。

二、避免不必要的設置,特別是在一對多和多對多的情況下,比如你現在操作的實體並不是在一個會話中得到,而是保存在 某些容器中,比如jsp的 SESSION中,雖然這樣的實體對象中有很多數據,但是如果你想得到這些實體對應的1對多或多對1的實體時,就會發現會出現session已經關閉的異 常。或則在你更新數據時出現not-null異常等。

---------------------------------------14----------------------------------------------

Remember that ordinal parameters are 1-based!

HQL語句有錯誤

---------------------------------------15---------------------------------------------

failed to lazily initialize a collection of role: XXXXXXXX no session or

這個異常大致意思是說在多對一的時候(並且lazy="false"),對象的實例失敗,多數出現的情況有

1、粗心造成

實例對象類名寫錯之類的

2、邏輯錯誤

如之前就已經傳遞過來一個實體對象,然後調用實體對象的方法時牽涉到1對多的情況,但此時SESSION已經關閉,所以根本無法進行一對多的操作。

3、設計到跨度的問題:

這樣打比方有多個實體對象,他們直接或則間接的有關聯。比如有4個實體,分別是廣告信息、廣告、廣告問答題、廣告商:他們之間的關系為:

廣告商 1:n 廣告

廣告 1:n 廣告問答題

廣告商 1:n 廣告商信息

大家可以看到廣告和廣告商信息是沒有直接關系的。但我要添加廣告的時候我就必須將廣告商的實體做為條件。那麽這麽一來廣告商信息可能間接的就必須用上。下面看我的操作:

ad(廣告),subject(題目)

Ad ad = new Ad();

ad.setAdProd(adform.getAdProd());

ad.setIndustry(industry);

ad.setAdPicture(pagefile.getFileName());

ad.setAdFlack(adform.getAdFlack());

ad.setAdDv(dvfile.getFileName());

ad.setAdContent(adform.getAdContent());

ad.setGray(gray);

ad.setAdDate(new Date());

ad.setOnlinetime(new Long(0));

//以上為廣告的基本信息填寫,而重要的是看下面一句,在這裏我的思路是subjectFormList是一個動態提交的表單,裏面有若幹個廣告問答題。我將這些問答題變為一個Set,然後作為ad的一個屬性。

Set<Subject> subjectset=getSubjectSet(subjectFormList,ad);

ad.setSubjects(subjectset);

//然後提交,makePersistent是一個封裝的方法,用途就是save()啦。addao是一個DAO,裏面有ADUS。

addao.makePersistent(ad);

表面上看來很符合邏輯,只要我們在ad的映射裏面加上對subject的級聯更新就可以完成這項操作。但實際上會發生我們意想不到的問題,來讓我們看一下getSubjectSet()的內容:

public Set getSubjectSet(List<SubjectForm> subjectlist,Ad ad)

{

Set<Subject> set=new HashSet<Subject>(0);

Subject subject;


for(Iterator<SubjectForm> it=subjectlist.iterator();it.hasNext();)

{

subject=new Subject();

SubjectForm sf=it.next();

subject.setSuContent(sf.getSucontent());

subject.setSuOption(sf.getSuoption());

subject.setSuResult(Arrays.deepToString(sf.getSuresult()));

subject.setSuType(String.valueOf(sf.getSutype()));

subject.setAd(ad);

set.add(subject);

}

return set;


}

我們在這個方法上設一個斷點然後跟蹤,之後你會發現斷點在set.add(subject)只後就會出failed to lazily initialize a collection of role: XXXXXXXX no session or session was closed這個異常,並且這個異常還是出在了廣告商的廣告信息上 gray.messages。是不是很不可理解?這也是Hibernate的懶漢機制問題。沒有任何一樣技術是完美的。那我們該怎麽處理這樣的問題。有很 多人以為我們在廣告商對廣告商信息的隱射上加lazy="false"這樣在對gray操作會對messages進行關聯,並查詢時提出數據。但你會發現 改完之後會出現org.hibernate.LazyInitializationException: illegal access to loading collection這個異常。並切lazy="false"是我們不推薦的一種方法。他會降低你的查詢效率。

對於這樣的情況最好的解決辦法就是不要偷懶,對一個實體進行操作的時候就該用那個實體的DAO,即應該有2句HQL。如下把getSubjectSet()改一改:

public void getSubjectSet(List<SubjectForm> subjectlist,Ad ad)

{

Set<Subject> set=new HashSet<Subject>(0);

SubjectDAO subjectdao=DAOFactory.getDao(SubjectDAO.class);

for(Iterator<SubjectForm> it=subjectlist.iterator();it.hasNext();)

{

Subject subject=new Subject();

SubjectForm sf=it.next();

subject.setSuContent(sf.getSucontent());

subject.setSuOption(sf.getSuoption());

subject.setSuResult(Arrays.deepToString(sf.getSuresult()));

subject.setSuType(String.valueOf(sf.getSutype()));

subject.setAd(ad);

subjectdao.makePersistent(subject);

//set.add(subject);

}


}//遍歷出所有subject一個個的往數據庫裏加。這樣便不會出問題了。

1、OpenSessionInView模式:

以下有2種方法,第1種是結合SPRING,第2種是采用了攔截器

Spring+Hibernate中, 集合映射如果使用lazy="true", 當PO傳到View層時, 出現未初始化session已關閉的錯誤,只能在dao先初始化

parent.getChilds().size();

Spring提供Open Session In View來解決這個問題, 有兩種方式

1. Interceptor

<!--</span><span style="COLOR: rgb(0,128,0)"> =========== OpenSession In View pattern ==============</span><span style="COLOR: rgb(0,128,0)">-->

<bean id="openSessionInViewInterceptor"

class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">

<property name="sessionFactory" ref="sessionFactory"/>

</bean>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<property name="interceptors" ref="openSessionInViewInterceptor"/>

<property name="mappings">

<props>

......

</props>

</property>

</bean>

2. Filter

<web-app>

<filter>

<filter-name>hibernateFilter</filter-name>

<filter-class>

org.springframework.orm.hibernate.support.OpenSessionInViewFilter

</filter-class>

</filter>

<filter-mapping>

<filter-name>hibernateFilter</filter-name>

<url-pattern>*.do</url-pattern>

</filter-mapping>

</web-app>

第2種解決方法:

Hibernate.initialize()強制加載關聯對象

---------------------------------------16----------------------------------------------

Hibernate的No CurrentSessionContext configured 解決方案

Hibernate No CurrentSessionContext configured!

當你使用 Hibernate session factory的getCurrentSession() 函數時候,你可能見到過"No CurrentSessionContext configured!"

出現這個問題,是因為你沒有正確配置 Hibernate internal session context management .

你只要在Hibernate.cfg.xml文件中添加下面的配置就可以了:

<property name="current_session_context_class">thread</property>

hibernate+struts+Spring常見異常