轉自:http://blog.sina.com.cn/s/blog_3f195d25010009r5.html
11問:爲什麼在向數據庫中插入長字符串時候部分自動丟失
在向數據庫中增加一條新的條目時,發現如果文字(有英文字母,也有漢字)數量特別大,超過1000個,則每次通過Hibernate,向一個String類型的字段中增加數據時,只有幾百個字可以增加進去,其他的自動丟失了。
答:這是由於字段長度設置不合理造成的。可以根據字符串實際長度考慮使用Text、LongText、或者Blob等字段類型。不同數據庫的字段類型稍有不同,可以參考相關手冊。另外需要注意的是一個漢字佔用兩個字節長度。
12問:爲什麼採用Hibernate的批量刪除方法來刪除大批量的記錄數據時速度特別慢
答:在使用Hibernate版本2.X時,不推薦採用Hibernate的批量刪除方法來刪除大量記錄。原因是,Hibernate會執行1條查詢語句,另外還有滿足條件的多條刪除語句,而不是一次執行一個刪除語句,所以當待刪除的數據很多時,會有很大的性能瓶頸。而對於Hibernate 3.0以上的版本,則不存這個問題。
13問:升級Hibernate 3後在導入hbm映射文件時爲什麼非常非常慢
原先在Hibernate 2中,程序的速度是非常快的。當環境順利從Hibernate 2升級到Hibernate 3後,發佈時在Tomcat的控制檯中發現:Hibernate 3裝載hbm映射文件時非常慢,差不多10秒鐘才能裝載一個hbm文件。
答:通過在Hibernate的源代碼中設置斷點,可以發現執行效率低下的代碼在org.hibernate.cfg.Configuration文件中的第240行:
addInputStream( new FileInputStream( xmlFile ) );
而addInputStream函數中又包含:
org.dom4j.Document doc = xmlHelper.createSAXReader( "XML InputStream", errors, entityResolver ).read( new InputSource( xmlInputStream ) );
跟蹤org.hibernate.util.XMLHelper中的函數createSAXReader可以得出結論,問題的癥結出在這一條語句:
org.dom4j.Document doc = xmlHelper.createSAXReader()
可以判斷這是在XML文件裝載初始化時發生的錯誤,仔細檢查XML文件,可以發現這是XML的第一行聲明dtd的錯誤,因爲以前使用的是Hibernate 2,所以hbm文件的dtd指向的是版本2,而升級Hibernate 3後,沒有把老的hbm映射文件換成版本3。在更換爲3版本後,此問題得到解決。
14問:爲什麼Hibernate 3中的HQL無法查詢漢字
使用同樣的代碼和配置文件,在Hibernate 2上完全沒有問題,在Hibernate 3中,使用如下HQL查詢,無法得到正確的結果集:
String hql = "from story where title like '%漢字%'";
Query q = session.createQuery(hql);
但用下面的HQL查詢,卻可以得到正確結果集:
String hql = " from story where title like '%english%'";
Query q = session.createQuery(hql);
答:如果採用的是拼接HQL的方式,從Hibernate 2升級到Hibernate 3確實會出現漢字亂碼問題。在控制檯中可以看到,SQL的漢字部分變成了亂碼:
[DEBUG] 2005-08-14 14:33:58 org.hibernate.SQL - "select story0_.content from story as story0_ where story0_.title like '%&–°é—&&`¨&'
在Hibernate中,查詢時應儘量使用佔位符的寫法(如下),這樣既可以避免亂碼問題,又可以避免潛在的SQL注入攻擊:
getHibernate().find("from story where title like ? ", "%漢字%")
15問:Hibernate 3中如何獲得庫表所有字段的名稱
答:可以使用以下的程序獲得。
Configuration conf = new Configuration();
conf.configure();
Iterator iter = conf.getTableMappings();
while ( iter.hasNext() ) {
Table table = ( Table ) iter.next();
System.out.println(table.getName());
Iterator ics = table.getColumnIterator();
while (ics.hasNext()){
Column col = (Column) ics.next();
System.out.println(col.getName());
}
}
16問:錯誤代碼:ObjectNotFoundException: No row with the given identifier exists
答:在以下幾種情況下,該錯誤可能會發生。
當試圖使用session.load()方法裝載一個未被代理的對象,或者訪問一個超出範圍的代理對象時。
當裝載一個未被正確取得的映射時。
當未被外鍵約束的外鍵字段中含有非法值時。
檢查裝載使用的主鍵Id,並驗證外鍵關係,以確定數據庫中已經存在相應的約束關係。堅持“在一個Session中只處理一個事務”的原則。因爲當在單一Session中使用多個事務時很容易犯錯。尤其注意,在一個HibernateException已經拋出後不要再操作Session。
17問:錯誤代碼:InvalidObjectException: Could not find a SessionFactory named: null
答:這個錯誤在以下幾種情況下經常發生。
試圖序列化一個已經失效的Hibernate Session,然後在另外一個虛擬機中進行反序列化。
類裝載器被重置,例如在未重啓的application server或者Web container中重新部署程序。在使用Tomcat時會經常遇到這個問題,這是因爲application server中一般使用JNDI來存儲SessionFactory,而在Tomcat或其他一些Web容器中,則是通過在context重載時,關閉HttpSession序列化來實現的。這種實現方式會引起這個錯誤發生。
18問:錯誤代碼:org.hibernate.HibernateException: CGLIB Enhancement failed: <classname>
答:Hibernate 3的默認方式是把所有類通過代理方式來進行延遲加載。如果代碼中的類有一個私有無參的構造器的話,Hibernate將無法在運行時將項目代碼中的類作爲子類裝載。爲了避免這個錯誤,類中的構造器函數至少應該在包內可見。
19問:爲什麼在Hibernate中添加、刪除、修改一個對象或Collection,但是數據庫中實際上沒有任何變化
答:這個問題經常會困擾初學者。這是因爲如果沒有使用Hibernate的自動事務處理,則必需顯式的提交事務,操作纔會在數據庫中執行。
20問:爲什麼保存一個父對象,而它的關聯對象沒有自動儲存到數據庫裏
答:關聯對象必需顯式的調用session.save()(或session.persist()),或者在關聯的映射文件中加入cascade="all"或cascade="save-update"(或cascade="persist")才能夠自動關聯執行。