Hibernate 常見異常
net.sf.hibernate.MappingException
當出現net.sf.hibernate.MappingException: Error reading resource:…異常時通常是由於映射文
件出現錯誤。
當出現net.sf.hibernate.MappingException: Resource: … not found是由於XML配置文件沒找到所致,有多是放置目錄不正確,或者沒將其加入hibernate.cfg.xml中。
2. net.sf.hibernate.PropertyNotFoundException
當出現net.sf.hibernate.PropertyNotFoundException: Could not find a setter for property
name in class …時,緣由通常是由於XML映射文件中的屬性與對應的Java類中的屬性的getter或setter方法不一致。
3. 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
的取值能夠爲increment、identity、sequence、hilo、native……等,更多的可參考hibernate參考文檔,通常取其值爲native 。具體可參考2.2.2.1小節。
4. a different object with the same identifier value was already associated with the session
當出現a different object with the same identifier value was already associated with the
session時,通常是由於在hibernate中同一個session裏面有了兩個相同標識可是是不一樣實體。
有以下幾種解決方案:
(1)使用session.clean(),若是在clean操做後面又進行了saveOrUpdate(object)等改變數據狀態的操做,有可能會報出"Found two representations of same collection"異常。
(2)使用session.refresh(object),當object不是數據庫中已有數據的對象的時候,不能使用
session.refresh(object)由於該方法是從hibernate的session中去從新取object,若是session中沒有這個對象,則會報錯因此當你使用saveOrUpdate(object)以前還須要判斷一下。
(3)session.merge(object),Hibernate裏面自帶的方法,推薦使用。
再次碰到:a different object with the same identifier value was already associated with the
session這個錯誤我一共遇到過兩次,一直沒有找到很好的解決方案,這個錯誤產生緣由相信你們都知道,由於在hibernate中同一個session裏面有了兩個相同標識可是是不一樣實體.
一開始按網上說的用session.merge(Object)報了一個錯,多是沒有用好,改用 session.clear();
session.update(user);這樣就OK了,
方法爲:
package org.springframework.orm.hibernate3.support;
...
public void modifyByMerge(User user) {
Session session = getHibernateTemplate().getSessionFactory().
getCurrentSession();
session.clear();
session.update(user);
}
...
項目用的是spring + hibernate因此得用getHibernateTemplate().getSessionFactory
().getCurrentSession();得當前Session
5. SQL Grammer Exception,Could not execute JDBC batch update
當出現SQL Grammer Exception,Could not execute JDBC batch update異常時,通常是由以下問題
引發:
(1)SQL語句中存在語法錯誤或是傳入的數據有誤;
(2)數據庫的配置不合法,或者說是配置有誤。較容易出現的有數據表的映射文件(,hbm.xml文件)配置有誤
;Hibernate.cfg.xml文件配置有誤;
(3) 當前的數據庫用戶權限不足,不能操做數據庫。以是以Oracle 數據庫爲例,這種狀況下在錯誤提示中
會顯示java.sql.BatchUpdateException: ORA-01031: insufficient privileges這樣的信息。
針對上面的各類緣由,開發人員能夠找出對應的解決方案。
16.net.sf.hibernate.QueryException: undefined alias:我猜測出項這種錯誤的緣由有不少種:多是大小寫問題,還有其餘不少種可能
17.net.sf.hibernate.NonUniqueResultException:檢索單個對象時,查詢結果包含多個對象,但沒有調用
setMaxResult(1)方法
18.net.sf.hibernate.QueryException: Not all named parameters have been set
使用setProperties()方法:用於把命名參數與一個對象的屬性值綁定時,對象中沒有匹配的名字相同的屬
性。
文章出處:http://www.diybl.com/course/3_program/java/javashl/2008410/108844_2.html
===========================
1 .Caused by: org.dom4j.DocumentException: Invalid byte 2 of 2-byte UTF-8 sequence. Nested
exception: Invalid byte 2 of 2-byte UTF-8 sequence.
若是出現這行錯誤說明你的XML配置文件有不規範的字符,檢查下。
2 .net.sf.hibernate.MappingException: Error reading resource: hibernate/Hello_Bean.hbm.xml
若是出現這行錯誤說明你的hibernate的XML配置文件有錯
3 .net.sf.hibernate.MappingException: Resource: hibernate/Hello_Bean.hbm.xml not found
若是出現這行錯誤說明hibernate的XML配置文件沒有找到,你應該把XML文件放在與你的類文件同個目錄下,
本文中是放在hibernate\classes\hibernate\目錄下,也就是跟Hello_Bean.class類文件一塊兒。
4 .net.sf.hibernate.PropertyNotFoundException: Could not find a setter for property name in class hibernate.Hello_Bean
若是出現這行錯誤說明你的xml文件裏設置的字段名name的值與Hello_Bean.Java類裏的getXXX或setXXX方法不一致。
5 .net.sf.hibernate.HibernateException: JDBC Driver class not found: org.gjt.mm.mysql.Driver
6.The database returned no natively generated identity value 。 主鍵沒有添加增量
===========================
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錯誤: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 column="sort_id"
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 ../> 中的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
沒法實例集合。
這個是問題在你當前的實體中有一個一對多需實例的對象。但這個對象卻沒法實例出來,說明一對多那個多
的一方實體有問題,多數狀況可能有:
一、數據庫該動過但代碼沒動
二、實體代碼有錯誤
---------------------------------------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的取值
能夠爲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的對象。
而後再對此對象進行更改後在更新。
這樣的好處是:
1、數據是最新鮮的。
2、避免沒必要要的設置,特別是在一對多和多對多的狀況下,好比你如今操做的實體並非在一個會話中得
到,而是保存在某些容器中,好比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對多的狀況,但此時SESSION已經
關閉,因此根本沒法進行一對多的操做。
三、設計到跨度的問題:
這樣打比方有多個實體對象,他們直接或則間接的有關聯。好比有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一個個的往數據庫里加。這樣便不會出問題了。
一、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
>
<property ref="sessionFactory"/>
</bean>
<bean
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property ref="openSessionInViewInterceptor"/>
<property >
<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 >thread</property>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^
hibernate實現類中的方法2009-02-22 12:52--增長
public void addUser(User user){
Session s=null;
Transation tx=null;
try{
s=HibernateUtil.getSession();//在HibernateUtil工具類中寫的
tx=s.beginTransation();
s.save(user);//要是刪除操做就改爲s.delete(user);要是更新:s.update(user);
tx.commit();
}catch(hibernateException e){
if(tx!=null){tx.rollback();}
trow e;
}finally{
if(s!=null){s.close();}
}
}html