xskow's road.

          做好自己,做好一切。
          數據加載中……
          華南理工大學校運會計分系統項目總結(一)
                  這么一個項目,確實,用了我很多時間,原因是自己在項目開始時可以說對SSH只有一知半解,就堅決地要采用這三個優秀框架來搭建服務。不過,學到的確實不少啊,起碼對于這樣的應用還是有一定底子了,呵呵。。。
                  在這個項目當中,有什么值得寫在我的小博客上面呢?有的。本項目分層也是采用經典的貧血模式。由底向上共四層,model-->dao-->service-->action。其中model采用Hibernate,底層數據庫用MySQL5,在Hibernate方面,我用了比較新的annotations,而不是平常的*.hbm.xml。確實,annotations用起來比較方便,但是和POJO的耦合度就大多了。記得有些配錯的時候要一個一個getter去找annotation,呵呵。。。
                  在Hibernate annotation方面,還是有些東西值得總結一下,首先就是annotation寫在是什么地方,最方便的方法是寫在各個field的getter上面,這樣就不用額外的annotation,也建議大家采用此方法,另一種也就是寫在field聲明上面,這樣的話需要在類上方添加其他annotation,我當時是沒成功,呵呵。其次是級聯操作,也就是cascade,需要注意的是當兩個實體關系是一對多和多對多的時候,比如班級與學生,學生與課程,明顯班級與學生是一對多,學生與課程是多對多關系,那么當我們需要設置級聯時候怎么辦呢?在hibernate中,cascade分有4種,分別是CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH,CascadeType.REMOVE。比如是persist,如果在剛才的例子來說,應該這樣配置:
           1//班級實體
           2@Entity
           3@Table(name="T_CLASS")
           4public class Clazz{
           5  
           6  private Set<Student> students;
           7  
           8  
           9  @OneToMany
          10  (cascade={CascadeType.REMOVE,CascadeType.MERGE, CascadeType.PERSIST}, fetch=FetchType.LAZY, mappedBy="clazz")
          11  public Set<Student> getStudents(){
          12    return students;
          13  }
           
          14}

          15

           1//學生實體
           2@Entity
           3@Table(name="T_STUDENT")
           4
           5public class Student{
           6  
           7  private Clazz clazz;
                   private Set<Course> courses;
           8  
           9  @ManyToOne
          10  @JoinColumn(name="CLAZZ_ID")
          11  public Clazz getClazz(){
          12    return clazz;
          13  }

          14  
                    @ManyToMany
                    @JoinTable(name="T_STUDENT_COURSE")
                    public Set<Course> getCourses(){
                          return courses;
                   } 
          15}

           1//課程實體
           2public class Course{
           3  
           4  private Set<Student> students;
           5  
           6  @ManyToMany(mappedBy="courses" cascade={CascadeType.PERSIST, CascadeType.REMOVE})
           7  public Set<Student> getStudents(){
           8    return students;
           9  }

          10}

          在Clazz的OneToMany和Course的ManyToMany中,我們都可以看到有CascadeType.PERSIST和CascadeType.REMOVE。具體到底是什么意思呢?persist是指當持久化實體的時候,如果有關聯的集合,并且設成persist時,連集合也一并存入數據庫當中。但是如果真正寫一下,然后使用的話,我們會發現:OneToMany設置這個根本不起作用。比如我新建一個班級,并直接賦予60個學生的一個集合,然后調用dao的save方法,看看數據庫,怎么回事,怎么只有班級持久化了,關聯學生一個沒存到數據庫?然后試試新建課程,并且選上要修這門課的學生,然后持久化課程,看看數據庫,怎么搞的,這次雙方都持久化了,即中間表已經插入了相關的記錄。造成OneToMany用persist是什么原因?個人理解:學生屬于一個實體,其持久化應當依靠自己相應的dao,一個一個student的存儲。就好比student和course的中間表,我們上面假設中間表只有STUDENT_ID和COURSE_ID,并且分別連向student表和course表的主鍵,如果你有特殊需求,比如是要一個score列(課程成績),那么這時候你還想用ManyToMany配置的話,會出現好多問題,除非你允許成績是空的,但是即使成績可以為空,如果你需要修改成績怎么辦呢?先取出這個學生,然后遍歷其課程集合,找到這個課程然后再持久化不行?應該可以吧,但是是不是指需要先刪除這個學生選的課程,然后再將這些再次持久化一次?這個方法絕對可以,不過我沒人會這樣。。。呵呵。。。當中間表有其他與兩方表都沒有關系的列時,你應當為中間表也映射一個實體,用這個實體的相應dao修改相應的記錄。在這種情況下用ManyToMany還有另一個問題,如果你的hibernate session還沒有關閉,你會發現提錯,說你打算刪除即將再次持久化的記錄。使用OpenSessionInViewFilter的時候你就會發現這個問題了。呵呵。。。
                  還有一個,Hibernate官方不推薦使用聯合主鍵,原來的我就不相信用聯合主鍵會怎樣,還不行嗎?要不行那還不是你框架太爛?實踐過之后,我改變了我的看法。。。假如你是普通的一個表,使用聯合主鍵沒有任何問題,但是假如你的表是一個中間表,并且有和兩個關聯表無關的列,就像T_STUDENT_COURSE,我們在設計數據庫的時候,很容易想到用STUDENT_ID和COURSE_ID來作為主鍵,不錯,但是如果你用hibernate映射實體的時候你知道有什么麻煩嗎?首先這兩個都是外鍵,在hibernate中就是需要有兩個關聯實體的對象引用,那么這兩個作為@Id是吧?可以啊!但是當你持久化的時候,會提示student在T_STUDENT_COURSE中無法找到。為什么?因為你數據庫就一個ID呀,而你這里配的可是一個實體引用呀!其實這也是可以解決了,就是解決辦法迂回一點點,在hibernate外鍵關聯的時候可以指定實體引用,就是說比如你StudentCourse實體,有一個student的引用,可以定義這樣一個column:studentId,這個Id可以關聯student引用,具體寫法我就不寫出來了,在hibernate官方文檔寫得相當詳細,很容易驗證。看,就一個外鍵都這樣了,多個外鍵還得了?當然,如果普通的單外鍵引用不會產生這樣的問題,直接配一個實體引用就可以解決問題。問題是可以解決的,關鍵是以后維護起來是否方便?我做過就知道,一點不簡單,所以后來還是改了。。。不推薦大家使用聯合主鍵。

          posted on 2008-11-10 20:39 xskow! 閱讀(862) 評論(1)  編輯  收藏 所屬分類: SSH探索

          評論

          # re: 華南理工大學校運會計分系統項目總結(一) 2008-12-17 22:28 ytl

          不錯,想你學習啦。可和你成為朋友不??我的QQ號是:543893878 Email:ytl_zlq@163.com
            回復  更多評論    
          links:
          主站蜘蛛池模板: 于田县| 磐安县| 玛多县| 紫阳县| 额尔古纳市| 岳普湖县| 德阳市| 烟台市| 承德县| 台中县| 顺昌县| 乐亭县| 涡阳县| 洛川县| 康保县| 太仆寺旗| 巫山县| 延长县| 西贡区| 芮城县| 达拉特旗| 本溪市| 海林市| 双城市| 丰城市| 黑龙江省| 疏附县| 安多县| 社旗县| 和林格尔县| 沙田区| 安远县| 广德县| 琼结县| 西丰县| 泗水县| 太原市| 博兴县| 阿坝| 陵川县| 沁阳市|