一只灰機

          藍色
          posts - 6, comments - 1, trackbacks - 0, articles - 0

          2010年11月17日

          一、基礎類
          1、《Thinking in java》,入門第一位是建立正確的概念。
          2、《Core Java》,我沒系統讀過,這本書更貼近實踐,更多API的介紹,同樣,更新也更頻繁。

          二、進階類
          1、《Effective Java》,在熟悉語法、API之后,你需要知道最佳實踐和陷阱,沒有比這本更好的。
          2、《Java Puzzlers》,通過謎題介紹一些你可能沒有注意到的邊角料,作為趣味讀物也不錯
          3、《深入Java虛擬機》,翻譯一般,但不可不讀,最好結合最新的JVM規范來讀。

          三、特定領域
          1、網絡編程:
          (1)
          O'Reilly的《Java nio》,很多人都推薦,我個人覺的一般,基本上只是個API更詳細的說明文檔,O'reilly的java系列很多都是這樣。
          (2)我更推薦這本《Fundamental networking in java》,由淺入深教你怎么做java網絡編程,并且介紹很多背景知識,甚至介紹了各種最佳實踐、網絡編程模型以及Java socket在不同平臺之間的差異等等。

          2、并發編程:
          (1)《Java Concurrency in Practic》,并發領域必讀經典。
          (2)《Java并發編程:設計原則與模式》,同樣是Doug lea的作品。
          (3) 《java threads》,入門讀物。

          3、web編程,這塊我許久未接觸了,就不推薦了,有興趣的朋友可以補充下。

          四、模式與設計

          1、《設計模式》,GOF的經典。
          2、《設計模式精解》,應該有最新版,個人認為更適合入門。
          3、《Head first設計模式》,更輕松的入門讀物。
          4、《企業應用架構模式》
          5、《分析模式——可復用對象模型》
          6、《面向模式的軟件體系結構》,國內貌似翻譯了3卷,絕對經典,可惜翻譯較差。
          7、《重構——改善既有代碼設計》,想寫好代碼必讀。
          8、《重構與模式》,給我印象很深的 xml構建的例子,在我的代碼里應用到了。

          五、方法論
          1、《敏捷軟件開發》
          2、《測試驅動開發》,你不一定要TDD,但是你一定要學會做單元測試。
          3、《Agile Java》,也可以作為java入門讀物。
          4、《快速軟件開發》
          5、《面向對象分析與設計》,OO設計必讀。
          6、《Unix編程藝術》,打開你的眼界。

          六、Java之外
          0、《代碼大全》,編程的百科全書,必讀。
          1、《unix網絡編程》,學習網絡編程必讀書。
          2、《C++網絡編程》上下兩卷,介紹ACE的,但是其中對各種模式運用的介紹非常值的一讀。
          3、《Joel說軟件》,編程文化
          4、《人月神話》、《人件》
          5、《卓有成效的程序員》,給我很大啟發的一本書。
          6、《程序員修煉之道》
          7、《計算機程序的構造與解釋》,必讀
          8、《算法導論》,可以作為參考書
          9、《深入理解計算機系統》
          10、《編譯原理》龍書,最新版用java解釋,我沒有讀完,順便提下。

          posted @ 2010-12-01 10:19 noaso 閱讀(160) | 評論 (0)編輯 收藏

          利用Javascript取和設FCKeditor值也是非常容易的,如下:

          // 獲取編輯器中HTML內容
          function getEditorHTMLContents(EditorName) {
              var oEditor = FCKeditorAPI.GetInstance(EditorName);
              return(oEditor.GetXHTML(true));
          }

          // 獲取編輯器中文字內容
          function getEditorTextContents(EditorName) {
              var oEditor = FCKeditorAPI.GetInstance(EditorName);
              return(oEditor.EditorDocument.body.innerText);
          }

          // 設置編輯器中內容
          function SetEditorContents(EditorName, ContentStr) {
              var oEditor = FCKeditorAPI.GetInstance(EditorName) ;
              oEditor.SetHTML(ContentStr) ;
          }

          FCKeditorAPI是FCKeditor加載后注冊的一個全局對象,利用它我們就可以完成對編輯器的各種操作。

          在當前頁獲得 FCK 編輯器實例:
          var Editor = FCKeditorAPI.GetInstance('InstanceName');

          從 FCK 編輯器的彈出窗口中獲得 FCK 編輯器實例:
          var Editor = window.parent.InnerDialogLoaded().FCK;

          從框架頁面的子框架中獲得其它子框架的 FCK 編輯器實例:
          var Editor = window.FrameName.FCKeditorAPI.GetInstance('InstanceName');

          從頁面彈出窗口中獲得父窗口的 FCK 編輯器實例:
          var Editor = opener.FCKeditorAPI.GetInstance('InstanceName');

          獲得 FCK 編輯器的內容:
          oEditor.GetXHTML(formatted); // formatted 為:true|false,表示是否按HTML格式取出
          也可用:
          oEditor.GetXHTML();

          設置 FCK 編輯器的內容:
          oEditor.SetHTML("content", false); // 第二個參數為:true|false,是否以所見即所得方式設置其內容。此方法常用于"設置初始值"或"表單重置"哦作。

          插入內容到 FCK 編輯器:
          oEditor.InsertHtml("html"); // "html"為HTML文本

          檢查 FCK 編輯器內容是否發生變化:
          oEditor.IsDirty();

          在 FCK 編輯器之外調用 FCK 編輯器工具條命令:
          命令列表如下:
          DocProps, Templates, Link, Unlink, Anchor, BulletedList, NumberedList, About, Find, Replace, Image, Flash, SpecialChar, Smiley, Table, TableProp, TableCellProp, UniversalKey, Style, FontName, FontSize, FontFormat, Source, Preview, Save, NewPage, PageBreak, TextColor, BGColor, PasteText, PasteWord, TableInsertRow, TableDeleteRows, TableInsertColumn, TableDeleteColumns, TableInsertCell, TableDeleteCells, TableMergeCells, TableSplitCell, TableDelete, Form, Checkbox, Radio, TextField, Textarea, HiddenField, Button, Select, ImageButton, SpellCheck, FitWindow, Undo, Redo

          使用方法如下:
          oEditor.Commands.GetCommand('FitWindow').Execute();

          = FCKConfig.BasePath + 'plugins/'
          // FCKConfig.Plugins.Add( 'placeholder', 'en,it' ) ;


          去掉//后,就相當于把placeholder這個插件功能加上了,fckeditor的插件文件都在/editor/plugins/文件夾下分類按文件夾放置的,對于fckeditor2.0來說,里面有兩個文件夾,也就是有兩個官方插件,placeholder這個文件夾就是我們剛才加上去的,主要用于多參數或單參數自定義標簽的匹配,這個在制作編輯模板時非常管用,要想看具體實例的話,大家可以去下載acms 這個系統查看學習,另一個文件夾tablecommands就是編輯器里的表格編輯用到的了。當然,如果你想制作自己其它用途的插件,那就只要按照 fckeidtor插件的制作規則制作完放置在/editor/plugins/下就行,然后再在fckeidtor.js里再添加 FCKConfig.Plugins.Add('Plugin Name',',lang,lang');就可以了。

          第二部分 ,如何讓編輯器一打開的時候,編輯工具條不出現,等點“展開工具欄”時才出現?Easy,FCKeditor本身提供了這個功能啦,打開fckconfig.js,找到

          FCKConfig.ToolbarStartExpanded = true ;
          改成
          FCKConfig.ToolbarStartExpanded = false ;
          就可以啦!

          第三部分,使用自己的表情圖標,同樣打開fckcofnig.js到最底部那一段


          FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/msn/' ;
          FCKConfig.SmileyImages = ['regular_smile.gif','sad_smile.gif','wink_smile.gif'] ;
          FCKConfig.SmileyColumns = 8 ;
          FCKConfig.SmileyWindowWidth    = 320 ;
          FCKConfig.SmileyWindowHeight = 240 ;

          上面這段已經是我修改過的了,為了我發表此文的版面不會被撐得太開,我把FCKConfig.SmileyImages那一行改得只有三個表情圖了。

          第一行,當然是表情圖標路徑的設置,第二行是相關表情圖標文件名的一個List,第三行是指彈出的表情添加窗口最每行的表情數,下面兩個參數是彈出的模態窗口的寬和高嘍。

          第四部分,文件上傳管理部分

          此部分可能是大家最為關心的,上一篇文章簡單的講了如何修改來上傳文件以及使用fckeidtor2.0才提供的快速上傳功能。再我們繼續再深層次的講解上傳功能

          FCKConfig.LinkBrowser = true ;
          FCKConfig.ImageBrowser = true ;
          FCKConfig.FlashBrowser = true ;在fckconfig.js找到這三句,這三句不是連著的哦,只是我把他們集中到這兒來了,設置為true的意思就是允許使用fckeditor來瀏覽服務器端的文件圖像以及flash等,這個功能是你插入圖片時彈出的窗口上那個“瀏覽服務器”按鈕可以體現出來,如果你的編輯器只用來自己用或是只在后臺管理用,這個功能無疑很好用,因為他讓你很直觀地對服務器的文件進行上傳操作。但是如果你的系統要面向前臺用戶或是像blog這樣的系統要用的話,這個安全隱患可就大了哦。于是我們把其一律設置為false;如下

          FCKConfig.LinkBrowser = false ;
          FCKConfig.ImageBrowser = false ;
          FCKConfig.FlashBrowser = false ;

          這樣一來,我們就只有快速上傳可用了啊,好!接下來就來修改,同樣以asp為范例進行,進入/editor/filemanager/upload/asp/打開config.asp,修改
          ConfigUserFilesPath = "/UserFiles/"這個設置是上傳文件的總目錄,我這里就不動了,你想改自己改了

          好,再打開此目錄下的upload.asp文件,找到下面這一段


          Dim resourceType
          If ( Request.QueryString("Type")
          <>"" ) Then
          resourceType = Request.QueryString("Type")
          Else
          resourceType = "File"
          End If
          然后再在其后面添加


          ConfigUserFilesPath = ConfigUserFilesPath & resourceType &"/"& Year(Date()) &"/"& Month(Date()) &"/"
          這樣的話,上傳的文件就進入“/userfiles/文件類型(如image或file或flash)/年/月/”這樣的文件夾下了,這個設置對單用戶來用已經足夠了,如果你想給多用戶系統用,那就這樣來改


          ConfigUserFilesPath = ConfigUserFilesPath & Session("username") & resourceType &"/"& Year(Date()) &"/"& Month(Date()) &"/"
          這樣上傳的文件就進入“/userfiles/用戶目錄/文件類型/年/月/”下了,當然如果你不想這么安排也可以修改成別的,比如說用戶目錄再深一層等,這里的Session("username")請根據自己的需要進行修改或換掉。

          上傳的目錄設置完了,但是上傳程序還不會自己創建這些文件夾,如果不存在的話,上傳不會成功的,那么我們就得根據上面的上傳路徑的要求進行遞歸來生成目錄了。

          找到這一段


          Dim sServerDir
          sServerDir = Server.MapPath( ConfigUserFilesPath )
          If ( Right( sServerDir, 1 )
          <>"\" ) Then
              sServerDir = sServerDir & "\"
          End If

          把它下面的這兩行


          Dim oFSO
          Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" )
          用下面這一段代碼來替換


          dim arrPath,strTmpPath,intRow
          strTmpPath = ""
          arrPath = Split(sServerDir, "\")
          Dim oFSO
          Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" )
          for intRow = 0 to Ubound(arrPath)
              strTmpPath = strTmpPath & arrPath(intRow) & "\"
              if oFSO.folderExists(strTmpPath)=false then
               oFSO.CreateFolder(strTmpPath)
              end if
          next
          用這段代碼就可以生成你想要的文件夾了,在上傳的時候自動生成。

          好了,上傳文件的修改到現在可以暫時告一段落了,但是,對于中文用戶還存在這么個問題,就是fckeditor的文件上傳默認是不改名的,同時還不支持中文文件名,這樣一來是上傳的文件會變成“.jpg”這樣的無法讀的文件,再就是會有重名文件,當然重名這點倒沒什么,因為fckeditor會自動改名,會在文件名后加(1)這樣來進行標識。但是,我們通常的習慣是讓程序自動生成不重復的文件名

          在剛才那一段代碼的下面緊接著就是
          ' Get the uploaded file name.
          sFileName = oUploader.File( "NewFile" ).Name
          看清楚了,這個就是文件名啦,我們來把它改掉,當然得有個生成文件名的函數才行,改成下面這樣

          '//取得一個不重復的序號
          Public Function GetNewID()
          dim ranNum
          dim dtNow
          randomize
          dtNow=Now()
          ranNum=int(90000*rnd)+10000
          GetNewID=year(dtNow) & right("0" & month(dtNow),2) & right("0" & day(dtNow),2) & right("0" & hour(dtNow),2) & right("0" & minute(dtNow),2) & right("0" & second(dtNow),2) & ranNum
          End Function

          ' Get the uploaded file name.
          sFileName = GetNewID() &"."& split(oUploader.File( "NewFile" ).Name,".")(1)

          這樣一來,上傳的文件就自動改名生成如20050802122536365.jpg這樣的文件名了,是由年月日時分秒以及三位隨機數組成的文件名了


          利用Javascript取和設FCKeditor值也是非常容易的,如下:

          // 獲取編輯器中HTML內容
          function getEditorHTMLContents(EditorName) {
              var oEditor = FCKeditorAPI.GetInstance(EditorName);
              return(oEditor.GetXHTML(true));
          }

          // 獲取編輯器中文字內容
          function getEditorTextContents(EditorName) {
              var oEditor = FCKeditorAPI.GetInstance(EditorName);
              return(oEditor.EditorDocument.body.innerText);
          }

          // 設置編輯器中內容
          function SetEditorContents(EditorName, ContentStr) {
              var oEditor = FCKeditorAPI.GetInstance(EditorName) ;
              oEditor.SetHTML(ContentStr) ;
          }

          FCKeditorAPI是FCKeditor加載后注冊的一個全局對象,利用它我們就可以完成對編輯器的各種操作。

          在當前頁獲得 FCK 編輯器實例:
          var Editor = FCKeditorAPI.GetInstance('InstanceName');

          從 FCK 編輯器的彈出窗口中獲得 FCK 編輯器實例:
          var Editor = window.parent.InnerDialogLoaded().FCK;

          從框架頁面的子框架中獲得其它子框架的 FCK 編輯器實例:
          var Editor = window.FrameName.FCKeditorAPI.GetInstance('InstanceName');

          從頁面彈出窗口中獲得父窗口的 FCK 編輯器實例:
          var Editor = opener.FCKeditorAPI.GetInstance('InstanceName');

          獲得 FCK 編輯器的內容:
          oEditor.GetXHTML(formatted); // formatted 為:true|false,表示是否按HTML格式取出
          也可用:
          oEditor.GetXHTML();

          設置 FCK 編輯器的內容:
          oEditor.SetHTML("content", false); // 第二個參數為:true|false,是否以所見即所得方式設置其內容。此方法常用于"設置初始值"或"表單重置"哦作。

          插入內容到 FCK 編輯器:
          oEditor.InsertHtml("html"); // "html"為HTML文本

          檢查 FCK 編輯器內容是否發生變化:
          oEditor.IsDirty();

          在 FCK 編輯器之外調用 FCK 編輯器工具條命令:
          命令列表如下:
          DocProps, Templates, Link, Unlink, Anchor, BulletedList, NumberedList, About, Find, Replace, Image, Flash, SpecialChar, Smiley, Table, TableProp, TableCellProp, UniversalKey, Style, FontName, FontSize, FontFormat, Source, Preview, Save, NewPage, PageBreak, TextColor, BGColor, PasteText, PasteWord, TableInsertRow, TableDeleteRows, TableInsertColumn, TableDeleteColumns, TableInsertCell, TableDeleteCells, TableMergeCells, TableSplitCell, TableDelete, Form, Checkbox, Radio, TextField, Textarea, HiddenField, Button, Select, ImageButton, SpellCheck, FitWindow, Undo, Redo

          使用方法如下:
          oEditor.Commands.GetCommand('FitWindow').Execute();


          posted @ 2010-11-24 08:42 noaso 閱讀(557) | 評論 (0)編輯 收藏

          關于Hibernate中 cascade 與 inverse 的理解。

          您買的Hibernate書是哪一本呢? 孫衛琴的精通Hibernate,還是 深入淺出Hibernate還是那本。。。
          我是兩本都買了,總體來說還可以,但是,有的地方講的比較書面化,比如inverse這屬性。

          在學習Hibernate的過程中最不好理解的就是這兩個屬性了。
          (我當初學習Hibernate的時候,發現網上介紹這兩個屬性的文章倒是不少,但是,居然有好多都是轉帖。。。還有的就是 照書搬~~-_-!!!)。。。

          據個例子:書上說inverse=false時,由主控方維持關系。。。
          由于我也是初學者。。。再加上語文水平偏低。。。不理解“維持關系是啥意思”囧~

          提示:
          (1)如果:您不了解Hibernate的one-to-many或many-to-one的概念。

          (2)如果:你不了解Hibernate的“自由態”“持久態”“游離態”的概念。

          (3)如果:您不了解Hibernate中的“臟數據”的概念。

          (4)如果:您對Hibernate中Session緩存,沒有初步了解的話。
          (在Hibernate中調用save進行存儲數據的時候,并不是馬上就對數據庫進行insert操作,而是會將其“數據對象(vo)”納入Hibernate的Session緩存。)

          在上面的4條提示中,如果您對其中的某一條,不是很清楚的話。希望請先了解有關知識。
          否則,可能您將 “無法或很難”理解 cascade 或 inverse 這2個屬性。

          首相,cascade 與 inverse 這兩個屬性,其實是完全不同的兩個東西,想要了解他們各自的“用途與區別”,詳見如下介紹:

          這里有兩個表:

          (1)class   (班級表)
          相應字段:
          cid    varchar(32) 主鍵 not-null (班級id)
          cname varchar(16)      not-null (班級名稱)  

          (2)student (學生表)
          相應字段:
          sid    varchar(32) 主鍵 not-null (學生id)
          sname varchar(16)      not-null (學生姓名)
          class_id varchar(32)   not-null (學生所屬班級)

          一個班級(class)對應多個學生(student),所以班級表(class)就是“one-to-many”端
          反之student就是many-to-one

          //--------Class類的代碼--------
          public class Class implements.....
          {
          private cId = "";
          private cName = "";
          private students = java.util.HashMap();
          // 省略對應的 geter setter
          }
          //--------Class.hbm.xml--------
          <hibernate-mapping>
          <class name="lcx.vo.Class" table="class"
             catalog="demo">
             <id name="cid" type="java.lang.String">
              <column name="cid" length="32" />
              <generator class="uuid.hex" />
             </id>
             <property name="name" type="java.lang.String">
              <column name="cname" length="16" not-null="true" />
             </property>
            
             <set name="students" table="student" cascade="save-update">
              <key column="class" />
              <one-to-many class="lcx.vo.Student" />
             </set>
          </class>
          </hibernate-mapping>

          //--------Student類的代碼;*******
          public class Student implements.....
          {
          private sId = "";
          private sName = "";
          private Class class = null;
          // 省略對應的 geter setter
          }
          // Student.hbm.xml
          <hibernate-mapping>
          <class name="lcx.vo.Student" table="student" catalog="demo">
             <id name="cid" type="java.lang.String">
              <column name="sid" length="32" />
              <generator class="uuid.hex" />
             </id>
             <many-to-one name="class"
              class="lcx.vo.Class"
              column="class_id"
              not-null="true"
             />   
          </class>
          </hibernate-mapping>

          (一) cascade 的介紹:
          當Hibernate持久化一個“臨時對象(也叫自由態對象)”時,在默認的情況下(即:沒有設置cascade屬性或cascade=none時),Hibernate不會自動“持久化他所關聯”的其他臨時對象。

          上面這些話是什么意思呢? 什么叫不會自動 “持久化”關聯的臨時對象呢?

          看如下代碼:

          // 創建一個 臨時對象(也叫自由態對象)
          // 也就是說這個 class 沒有被Hibernate納入Session緩存管理。
          Class class = new Class();
          //class.id 為自動生成
          class.setName("一年級1班");

          Student stu = new Student();
          //student.id 為自動生成
          stu.setName("小白兔");
          stu.setClass(class);

          // 關鍵就是這里。。。
          class.getStudents().add(stu);

          session.save(class);
          // 提交

          // 注意: Class.hbm.xml文件中,cascade="save-update"并且也沒有設置inverse屬性,也就是說inverse=false;
          // 此時如果你開啟了Hibernate的顯示HQL語句功能,那么控制臺將會顯示如下3條HQL:

          //----------------------------------------********
          insert into demo.class (cid, cname) values (66666666666666666666666666666666, 一年級1班)
          insert into demo.student (sid,sname,class_id) values (8888888888888888811cb2e04c888888, 小白兔, 66666666666666666666666666666666)
          update demo.student set class_id=66666666666666666666666666666666 where sid=8888888888888888811cb2e04c888888
          //----------------------------------------********

          那么為什么會出現,這3條HQL語句呢,我們來一一分析一下:

          第1條HQL語句:
          其實第一條HQL比較好理解,
          當我們調用 session.save(class) 后,在Hibernate進行提交的時候,
          會發現“有”一條“新”的數據要插入(insert),所以就往class表中,插入了這條新的class記錄。

          第2條HQL語句:
          注意問題就在這里:
          這里為什么又出現了一條insert語句呢?而且還是向student表中插入數據。
          我們在上面的代碼中,并沒有編寫類似“session.save(student)”這樣的語句啊。
          這是為什么呢?
          其實原因,是這么回事:因為我們在class端,設置了"級聯更新"(即:cascade="save-update"),
          也就是說,當Hibernate在向class表中插入“新”對象記錄時,會檢查“Class對象”所關聯的屬性(就是<set>對應的屬性),是否發生過變化,如果發生了變化,就按照“級聯屬性(cascade)”所設定的內容
          進行操作。

          上面講的這句話到底是什么意思呢?
          用你們“人”話說,就是:
          因為調用了 class.getStudents().add(stu);
          所以,在Hibernate在進行插入 class對象的時候,發現class對象,所關聯的集合中,有一條
          “自由態”的對象,而又因為class端設置了“級聯屬性cascade”,所以,在插入這條 “新class對象”時,也一同把他內部的那些,還屬于“自由態”的其他對象,也一同插入到,他們所對應的表中去了。

          還是不明白的話。。。可以看看。孫衛琴的《精通Hibernate》,在書上的第149頁有。
          但是關于inverse的介紹。。。寫的就有些書面化了,如果語文不好的話。。。就難懂咯~

          第3條HQL語句:
          第三條HQL語句是一條update語句,是不是覺得,很莫名其妙。。。。
          Hibernate大腦進水了吧,怎么吃飽了撐得,重復更新記錄啊啊啊啊啊
          假如:我們把 class端的配置文檔中的 invser屬性設置為true(即:inverse=true)
          在執行上面的程序,發現,就變成2條insert語句啦。。。。。(update沒啦。。。)
          看來第三條的update語句和inverse有著密切的關系(他兩有一腿~)。

          所以我們下邊,就來介紹一下inverse屬性:

          當調用 Class.getStudents().add(stu)方法,進行添加操作時,
          (即:向 "這個Class對象"所屬的“集合 (也就是調用getStudents方法所返回的那個Set集合)”中添加一個Student(即 add(stu)),也就是說,這個“新”添加的Student對象(stu),
          他的Student.class_id字段“必須”,要等于“被添加方Class”的主鍵(即:Class.cid)。
          從“數據庫”層面來講,也就是說,這個“新”添加的“Student”的class_id字段,必須要與“Class”的cid字段,存在"主外鍵關聯"。)

          正因為如此:所以Hibernate“怕” 在進行 "Class.getStudents().add(stu)" 這樣的操作時,
          出現意外情況(如: stu.getClass=null,即:stu沒有所屬班級),
          即“添加方”(Student)與“被添加方”(Class),存在“外鍵”不一致的情況發生。
          所以就出現了 那條多余的update語句。即:one-to-many(Class端)主動去維護Child.Class_id
          所以就是說,Hibernate怕出錯,就給你多執行一次無用的更新語句,以保證 add 到 Class“集合”中的所有Student
          都是要與Class有外鍵關聯的。

          用普通話說就是:
          一年1班.getStudents().add(小白兔);
          一年1班.getStudents().add(大白兔);

          也就是說現在不管是 小白兔 還是 大白兔
          如果他們,目前還沒有自己的班級的話,
          一年1班的班主任就會主動邀請他們成為一年1班的同學啦~。

          也就是說 一年1班的班主任 主動邀請 同學,而不是 同學自己來~~~ 所以效率也降低了。。。。

          所以我們一般把 一對多端 invser設置為true,即:不讓主控端去維護主鍵關聯,
          (即:讓同學自己去找班級)
          說白了,就是,one-to-many端不用去管理 “新添加對象” 的主外鍵約束問題。

          把one-to-many端(即:class端)的invser設置為true
          (即:每次向class.getStudents這個集合中添加 student時,不去主動update對應的外鍵),
          而是在student端去手動設置
          例如:
          student.setClass(class);
          session.save(student);
          這樣手動設置 student與class關聯啦。。。。
          所以上面的程序“最好”還是寫成這樣:

          Class class = new Class();
          class.setName("一年級1班");
          session.save(class);

          Student stu = new Student();
          stu.setName("小白兔");
          stu.setClass(class);
          session.save(class);

          /*
          此時向class集合add內容,不會進行數據庫操作(update)。
          “更新”的只是session緩存中,數據鏡像。
          這樣做的好處是:不僅減少了update語句,
          而且,同時也更新了session緩存。
          ------------------------
          而在原來:
          one-to-many端inverse=false時,雖然也更新seesion緩存中的class集合,
          但是有卻又多余update
          */
          class.getStudents().add(stu);
          // 提交

          總結:
          當inverse=false 并且向one-to-many端的關聯集合,添加“新對象(即: 自由態對象)” 時,
          Hibernate就會自動,去update那“個剛剛到來的” “自由態對象”的外鍵。
          (如果你向,one-to-many端添的集合中,add一個“已經持久化了的對象”,那就不會出現update了(因為已經持久化過了),除非,你去 更改“那個持久化對象”所對應的外鍵。。。那樣的話。。。呵呵呵~~~
          你可以試一試,應該不會報錯,你可以當做練習去做一下,加深cascade和inverse這兩個屬性的理解)


          // 如果看懂了上面的內容。來看一下,下面的東西。
          假如,將one-to-many端(即:Class端)的 hbm.xml 文檔中的cascade移除掉 或把cascade="none"。
          那么上面的代碼會出現什么情況呢。
          結果會出現2條HQL,和一堆Exception

          insert into demo.class (cid, cname) values (66666666666666666666666666666666, 一年級1班)
          update demo.student set class_id=66666666666666666666666666666666 where sid=8888888888888888811cb2e04c888888
          Hibernate Exceptinon......................................

          相比較cascade被設置"save-update"的時候,缺少了1條 insert語句,而且也多了一些Exception。

          那么,到底是少了哪1條insert語句呢?
          就是這條:
          insert into demo.student (sid,sname,class_id) values (8888888888888888811cb2e04c888888, 小白兔, 66666666666666666666666666666666)

          之所以會出現,這樣的現象,想必您已經早就看出來了。
          因為,我沒有設置Class端的Cascade,所以在save(class)的時候,并沒有自動將其所關聯的“自由態對象”進行持久化操作。
          然而,又因為 Class端的inverse=false,所以,Class會自動去維持,那個 “新來的student” 的外鍵。
          所以會出現,沒有insert就要update啦。。。。
          然后在就是Exception了

          posted @ 2010-11-17 13:31 noaso 閱讀(124) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 新丰县| 高尔夫| 贵定县| 噶尔县| 滕州市| 靖安县| 瓮安县| 揭西县| 汉源县| 周口市| 舟山市| 于田县| 文昌市| 扎兰屯市| 定日县| 常德市| 黔东| 龙陵县| 建昌县| 灌阳县| 阿坝| 静乐县| 封开县| 修文县| 延长县| 台北市| 阳原县| 苏尼特右旗| 民勤县| 铜山县| 恩平市| 天水市| 麟游县| 萨迦县| 嘉鱼县| 安阳县| 海宁市| 甘肃省| 同江市| 康保县| 麻城市|