一、使用hibernate進行更新操做時,首先調用了findById方法獲取要修改的對象,此時session沒有被關閉,接着從新建立一個對象,將要修改的屬性值賦值給這個對象。調用修改方法拋出以下異常:html
緣由:在session緩存中已經存在一個與當前傳遞進來的修改對象具備相同標識符(主鍵)的對象。Hibernate的機制是隻能存在一個具備惟一標示的對象,不然增刪改就會出錯。java
解決辦法:sql
:在使用過濾器/攔截器時,每次開啓session,操做後就關閉session。數據庫
‚:session.evict(Object object),從緩存中清除指定的對象。json
ƒ:session.clear(),是將session緩存中的對象所有清除,殺傷面太大了,不建議使用。緩存
二、HibernateSessionFactory類中有一個線程ThreadLocal類的對象,它用來分配session對象,經測試後發現,由它每回獲取的session都不一樣,有時爲空,有時能夠獲得以前存進去的session對象。session
三、若是使用struts+hibernate框架實現數據庫的增刪改,使用過濾器去開啓和提交事務時,有時增刪改會沒有效果,由於action沒有被過濾器過濾,這個使我困惑了好久,由於以前的項目均可以被過濾到,後面我想用攔截器攔截action,在攔截器中開啓和提交事務,試驗以後發現此法可行。框架
四、使用hibernate+struts框架開發項目時,系統拋出以下異常:異步
Exception:jsp
java.lang.reflect.InvocationTargetException
root Cause:
java.lang.NoSuchMethodError: antlr. Collections.AST.getLine()I
緣由:因爲我用的是MyEclipse自動生成的struts和hibernate類庫,hibernate中有個antlr-2.7.7.jar,而struts中有個antlr-2.7.2.jar。異常的緣由就是說沒有找到antlr.Collections.AST類中的getLine()方法,高版本的jar中有getLine()方法,而低版本中沒有getLine()方法,系統默認使用的是低版本的jar包。
解決辦法:去除struts類庫中的antlr.jar包便可,還須要清理並構建這個項目,由於有的項目的配置信息一時更改不過來。
五、Struts的類型轉換器用於將String類型轉化爲指定的數據類型,還能夠將指定的數據類型轉化爲String類型。開發項目時很方便。
實現方法:
:新建一個類繼承StrutsTypeConverter類,實現其中的兩個抽象方法,做爲轉換器類。
‚:新建局部屬性文件或者全局屬性文件
局部屬性文件:放置在相關action類同級目錄下,文件名格式:action類名-conversion.properties
裏面存放鍵值對,如:hobbies=util.ListConverter
hobbies就是要轉化的屬性名,util.ListConverter就是轉換器類的徹底限定名。
全局屬性文件:放置在src目錄下,文件名格式:xwork-conversion.properties
裏面存放鍵值對,如:java.util.Date=util.DateConverter
java.util.Date就是要轉化的數據類型,util.DateConverter
就是轉換器類的徹底限定名。
注意:若是咱們使用<s:property/>標籤,那麼它會調用轉換其中的convertToString(),若是使用EL表達式,那麼就不會調用該方法了。
六、針對類型轉換出錯的處理--在頁面上顯示友好提示:
類型轉換出錯時,要拋出一個運行時異常,程序會根據創建的屬性文件,顯示錯誤提示。
實現方法:
:新建局部屬性文件或者全局屬性文件
局部屬性文件:放置在相關action類同級目錄下,文件名格式:action類名.properties
裏面存放鍵值對,如:invalid.fieldvalue.time=mistake
invalid.fieldvalue.time就是出錯的字段名,mistake是錯誤提示信息。
全局屬性文件:放置在src目錄下,文件名格式:message.properties,屬性文件的名稱不做要求。
還要在struts.xml中配置一個常量:
<constant name="struts.custom.i18n.resources" value="message"/>
屬性文件中存放鍵值對,如:xwork.default.invalid.fieldvalue=fieldname is {0} is error
這是固定的格式,{0}表明錯誤的字段名,系統會自動賦值。
fieldname is {0} is error 即是提示信息。
七、Struts框架有相似於html的標籤,可是它有必定的格式,
可是咱們能夠在struts.xml中配置一個常量,去掉它的格式。
<constant name="struts.ui.theme" value="simple"/>
八、當咱們顯示錯誤信息的時候,會發現錯誤信息會以列表的形式顯示,這樣就不美觀了,達不到咱們想要的標準。因此咱們能夠用另外的方式輸出錯誤信息。
例如我如今增長了兩個錯誤信息:
this.addFieldError("username","用戶名太長!");
this.addFieldError("username","2222!");
那麼我就可使用如下四種方法輸出錯誤信息:
<s:property value="errors.username[0]"/>
‚ <s:property value="fieldErrors.username[0]"/>
ƒ ${errors["username"][0] }
4 ${fieldErrors["username"][0] }
原理:在值棧中有fieldErrors和errors兩個對象,這兩個對象中存儲着錯誤信息,利用<s:debug/>能夠觀察到,這兩個對象其實就是map數據類型的。
獲取map數據的方法:
九、Struts上傳文件
jsp部分:
struts.xml部分:
action部分:
注意:
文件對象名就是表單文件控件的name
文件類型的命名=文件對象名+FileContentType
文件名稱的命名=文件對象名+FileName
十、struts下載文件
jsp部分:
struts.xml部分:
action部分:
十一、兩級聯動
演示:
原理:
將數據庫中的數據封裝成對象,而後將對象轉化爲json數據,在客戶端用異步獲取後臺的json數據便可。
客戶端jsp頁面:
後臺:
注意:在js中若是某個元素還未被加載,那麼只能夠得到該元素的引用,不能對該元素進行綁定事件。
1三、在struts框架中使用json
客戶端:
Struts.xml:
UserAction:
注意:struts類庫裏面沒有提供ezmorph-1.0.6.jar文件,因此要手動添加。
1四、hibernate中的cascade屬性
Cascade屬性是存在於set標籤中,用來作級聯刪除和保存。
它的值有如下幾種:
默認值是none,不作級聯動做;
save-update:級聯保存
delete:級聯刪除
all:級聯保存和刪除
注意:屬性名稱和屬性值都嚴格需分大小寫
1五、hibernate中的inverse屬性
修改街道對應的區道信息:
修改後會發現程序執行了兩次修改操做:
緣由:
區道與街道是一對多的關係;
因爲Hibernate是雙向維護外鍵,因此當修改區道中的街道時,會修改一次外鍵;在修改街道中的區道時,又會修改一次外鍵。
這樣就會產生效率慢的問題,由於若是執行兩次修改,那麼第二次是無用的操做。利用inverse屬性能夠解決這一問題。
在區道表的映射文件裏面的set標籤中設置inverse屬性爲true;
inverse的屬性值以下:
默認值爲false,表示我方不放棄維護外鍵的權利
true,表示我方放棄維護外鍵的權利
一個國家有一個主席,國家有不少人,主席不可能認識國家的全部人,可是國家全部人能夠認識主席。
1六、延遲加載
延遲加載分爲類級別延遲和關聯級別延遲。
類級別延遲:
使用load(),例如:
只有當使用這個對象時纔會進行查詢,如輸出str和str.getName()時就會執行查詢語句,可是str.getId()並不會進行查詢。
關聯級別延遲:
使用set標籤中的lazy屬性,lazy的屬性值有true(默認值)、false、extra(極其懶惰,要什麼才查什麼);
懶加載的意思就是當你使用到對象中的關聯對象時,才執行查詢操做。
如當lazy=」true」時,當你使用set時才執行查詢操做。
如當lazy=」false」時,當你獲取District對象時,同時會查出全部的Street。
如當lazy=」extra」時,用什麼查什麼。
如我要查詢set.size(),系統會執行一下的查詢語句:
1七、fetch屬性
fetch的屬性值有select(默認值)、join、subselect
當fetch=」select」時,程序會先查詢返回要查詢的主體對象,而後根據lazy屬性看是否懶加載。
當fetch=」join」時,程序會將主體對象和關聯對象用一句鏈接查詢的sql同時查詢出來,這樣以來,懶加載就無用武之地了。
subselect和select同樣,不會一開始就將關聯對象查出來。
subselect與select的區別:
設置不執行懶加載;
select是根據關聯外鍵的id,每個對象發一個select查詢,獲取關聯的對象。
執行的sql以下所示:
而subselect是發送兩條sql語句,一條是查詢主體對象,而另外一條是抓取在前面查詢到的全部實體對象的關聯集合。
執行的sql以下所示:
1八、批量抓取
批量抓取的使用場景是查詢出來一個集合,而後又查詢每一個集合對象中的集合。使用set標籤中的batch-size屬性實現。
數據庫中只有5個區道信息;
設置batch-size=」5」,執行的查詢語句以下:
而設置batch-size=」7xxx」,執行的查詢語句以下:
因爲發送sql數據的次數多少,因此batch-size的數值越大,效率就越高。
當batch-size爲4時,首先會有4個?號,接着一個查詢語句會有1個?號。
1九、QBC查詢
格式:
qbc的統計查詢得使用projection實現,有兩種方式:
(1)
(2)
查看文檔發現ProjectionList和Projection的關係以下所示:
可使用groupProperty投影對結果集進行分組(使用SQL的GROUP BY子句),當你經過某個屬性分組時,程序就會查詢出該屬性所對應的列名。
可使用Property.forName()來表示投影,就是查詢指定的字段。
建立別名有三種方式:
20、離線查詢:
離線查詢使用DetachedCriteria對象設置限制條件,而後再經過session獲取Criteria對象。
離線查詢的使用場景:例如Biz類和Dao類,在Dao類中利用session操做CRUD,若是你想在Biz中設置限定條件,若是不使用離線查詢,那麼勢必得獲取Criteria對象,如此一來又得獲取session,有點麻煩。
可是使用離線查詢的話,能夠直接獲取DetachedCriteria對象設置限定條件,而後再將這個對象傳遞到Dao中便可。
概念:
投影就是指部分字段,例如我只查詢學生表中的姓名,這就叫投影。
CRUD是指在作計算處理時的增長(Create)、讀取查詢(Retrieve)、更新(Update)和刪除(Delete)幾個單詞的首字母簡寫。