Junky's IT Notebook

          統計

          留言簿(8)

          積分與排名

          WebSphere Studio

          閱讀排行榜

          評論排行榜

          HIBERNATE學習筆記(轉)

          Hibernate 學習筆記

          一 hibernate配置
          1.下載所需包
          下載hibernate2.13, hibernate-extension2.13,Middlegen(已裝了jdk和ant)
          2.創建數據庫(例子:student;course,stu_cou)
          Student(id,name)
          Course(id,name)
          Stu_cou(stu_id,cou_id)(分別是student表和course表的外健)
          3.使用MiddleGen(見附錄)

          二 hibernate映射關系(many-to-many)
          1. 分析inverse參數(student.hbm.xml course.hbm.xml)
          inverse該參數用來負責映射之間的關系,設置為false的一方可以對他們的關系進行維護
          設置inverse = false的實體,表示在映射中是它是主動關系,由它來維戶關系中的數據
          設置inverse = true 的實體,表示在映射中是它是被動關系,它不維護關系中的數據
          1) inverse=false的情況
          a) 添加記錄的情況
          student.hbm.xml是主動方,由它來決定stu_cou表中的記錄,故inverse=false
          當向stu_cou中寫入記錄時候,
          /*
          * 測試目的:在stu_cou中添加一組對應關系(student,course)
          * 測試結果:當執行完該段代碼后
          * 如stu_cou中沒有(student,course)時,自動加入(student,course)
          * 如stu_cou中存在(student,course)時,什么都不作,不會存在主健沖突
          Student student=(Student)session.load(Student.class,student2.getId())
          Course course=(Course)session.load(Course.class,course2.getId());
          student.getCourses().add(course);
          session.save(student);
          執行完后,hibenrate成功顯示
          Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?
          Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?
          Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?
          Hibernate: insert into stu_cou (sid, cid) values (?, ?)
          b) 刪除記錄的情況
          Student student=(Student)session.load(Student.class,student2.getId())
          Course course=(Course)session.load(Course.class,course2.getId());
          student.getCourses().讓remove(course);
          session.save(student);
          代碼執行完后,可以成功執行,hibernate顯示:
          Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?
          Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?
          Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?
          Hibernate: delete from stu_cou where sid=?

          2) inverse=true的情況
          student.hbm.xml是被動方,設置它的inverse=true
          a) 添加記錄情況
          * 測試目的:在stu_cou中添加一組對應關系(student,course)
          * 測試結果:當執行完該段代碼后
          * 如stu_cou中沒有(student,course)時,自動加入(student,course)
          * 如stu_cou中存在(student,course)時,什么都不作,不會存在主健沖突
          Student tudent=(Student)session.load(Student.class,student2.getId());
          Course course=(Course)session.load(Course.class,course2.getId());
          student.getCourses().add(course);
          session.save(student);
          代碼執行完后,hibernate顯示,沒有插入記錄
          Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?
          Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?
          Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?

          b) 刪除記錄情況
          當向stu_cou中刪除記錄時候,
          Student student=(Student)session.load(Student.class,student2.getId())
          Course course= (Course)session.load(Course.class,course2.getId());
          student.getCourses().remove(course);
          session.save(student);
          執行完,hibernate顯示如下,證明沒有刪除記錄
          Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?
          Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?
          Hibernate: select courses0_.cid as cid__, courses0_.sid as sid__ from stu_cou courses0_ where courses0_.sid=?
          Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?
          Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_ where course0_.id=?

          2. 分析cascade參數(student.hbm.xml course.hbm.xml)
          只有設置了inverse=false才可以操縱stu_cou的數據
          當inverse=true的時候,下列情況1中b)提示錯誤
          原因: stu_cou中存在外健約束,你無法直接刪除student表中的數據
          1) cascade=save-update的情況
          a)添加記錄情況
          Set set=new HashSet();
          set.add(course1);
          set.add(course2);
          set.add(course3);
          student3.setCourses(set);
          session.save(student3);
          執行后hibernate提示:
          Hibernate: insert into student (name) values (?)
          Hibernate: insert into course (name) values (?)
          Hibernate: insert into course (name) values (?)
          Hibernate: insert into course (name) values (?)
          Hibernate: insert into stu_cou (sid, cid) values (?, ?)
          可見,插入了student,course,和stu_cou三個表

          b)刪除記錄情況
          Student student=(Student)session.load(Student.class,new Integer(22));
          session.delete(student);
          成功執行后,hibernate提示:
          Hibernate: select student0_.id as id0_, student0_.name as name0_ from student student0_ where student0_.id=?
          Hibernate: delete from stu_cou where sid=?
          Hibernate: delete from student where

          2) cascade=all的情況
          a) 添加記錄情況
          Set set=new HashSet();
          set.add(course1);
          set.add(course2);
          set.add(course3);
          student3.setCourses(set);
          session.save(student3);
          執行后hibernate提示:成功添加級聯關系
          Hibernate: insert into student (name) values (?)
          Hibernate: insert into course (name) values (?)
          Hibernate: insert into course (name) values (?)
          Hibernate: insert into course (name) values (?)
          Hibernate: insert into stu_cou (sid, cid) values (?, ?)
          b) 刪除記錄情況
          Student student=(Student)session.load(Student.class,new Integer(22));
          session.delete(student);
          測試結果(所有和student(22)相關的記錄均被刪除)
          刪除student表中的student(22)記錄
          刪除stu_cou表中的student(22)的記錄
          刪除course表中的student(22)對應的course的記錄

          2) cascade=none情況
          a) 添加記錄情況
          Set set=new HashSet();
          set.add(course1);
          set.add(course2);
          set.add(course3);
          student3.setCourses(set);
          session.save(student3);
          失敗,因為沒有級聯關系,所以course記錄添加不進去,造成外健失敗

          b) 刪除記錄情況
          Student student=(Student)session.load(Student.class,new Integer(22));
          session.delete(student);
          正常,刪除了student表中的記錄student(22),同時刪除了stu_cou中對應的student(22)的記錄

           

          附錄
          1.MiddleGen的使用
          1環境變量設置
          %Hibernate_Home%/lib/*.jar到%MiddleGen%/lib下
          %Hibernate_Home%/hibernate2.jar到%MiddleGen%/lib下
          %Hibernate-Extension_Home%/tools/lib/*.jar到%MiddleGen%/lib下
          %Hibernate-Extension_Home%/tools/hibernate-tools.jar到%MiddleGen%/lib下

          2 MiddleGen的配置
          配置目標數據庫參數
          進入MiddleGen 目錄下的\config\database 子目錄,根據我們實際采用的數據庫打開對應的配置文件。如這里我用的是mysql數據庫,對應的就是mysql.xml文件。
          <property
          name="database.script.file" value="${src.dir}/sql/${name}-mysql.sql"/>
          <property
          name="database.driver.file" value="${lib.dir}/mysql.jar"/>
          <property
          name="database.driver.classpath" value="${database.driver.file}"/>
          <property
          name="database.driver" value="org.gjt.mm.mysql.Driver"/>
          <property
          name="database.url" value="jdbc:mysql://localhost/sample"/>
          <property
          name="database.userid" value="user"/>
          <property
          name="database.password" value="mypass"/>
          <property
          name="database.schema" value=""/>
          <property
          name="database.catalog" value=""/>
          <property
          name="jboss.datasource.mapping" value="mySQL"/>
          其中下劃線標準的部分是我們進行配置的內容,分別是數據url以及數據庫用
          戶名和密碼。

          1) 修改Build.xml
          修改MiddleGen 根目錄下的build.xml 文件,此文件是Middlegen-Hibernate 的Ant構建配置。Middlegen-Hibernate將根據build.xml文件中的具體參數生成數據庫表映射文件。可配置的項目包括:

          a) 目標數據庫配置文件地址
          查找關鍵字 ”!ENTITY”,得到:
          <!DOCTYPE project [
          <!ENTITY database SYSTEM
          "file:./config/database/hsqldb.xml">
          ]>
          默認情況下,MiddleGen 采用的是hsqldb.xml,
          將其修改為我們所用的數據庫配置文件(mysql.xml):
          <!DOCTYPE project [
          <!ENTITY database SYSTEM
          "file:./config/database/mysql.xml">
          ]>

          b) Application name
          查找:
          <property value="airline"/>
          “aireline”是MiddleGen原始配置中默認的 Application Name,將其修改為我們
          所希望的名稱,如“HibernateSample”:
          <property value="HibernateSample"/>

          c) 輸出目錄
          查找關鍵字“name="build.gen-src.dir"”,得到:
          <property
          value="${build.dir}/gen-src"/>
          修改value="${build.dir}/gen-src"使其指向我們所期望的輸出目錄,
          這里我們修改為:<property
          value="C:\sample"/>
          d) 對應代碼的Package name
          查找關鍵字“destination”,得到:
          <hibernate
          destination="${build.gen-src.dir}"
          package="${name}.hibernate"
          genXDocletTags="false"
          genIntergratedCompositeKeys="false"
          javaTypeMapper=
          "middlegen.plugins.hibernate.HibernateJavaTypeMapper"
          />
          可以看到,hibernate 節點package 屬性的默認設置實際上是由前面的
          Application Name (${name})和“.hibernate”組合而成,根據我們的需要,
          這里還有一個屬性genXDocletTags,如果設置為true,則生成的代碼將包含
          xdoclet tag,這為以后在開發過程中借助xdoclet進行映射調整提供了幫助。注意,如果使用的數據庫為SQLServer,需要將build.xml部分刪除(參見夏?^的文檔),否則Middlegen會報出找不到表的錯誤。
          至此為止,MiddleGen 已經配置完畢,在MiddleGen 根目錄下運行ant,就將出現
          MiddleGen的界面:
          2 *.xml到.java
          在得到.xml后,使用ant hbm2java 即可得到相應的java文件
          總結:
          我第一次運行成功,但是后來則出現如下類似錯誤,檢查發現在MiddleGen的lib目錄下存在多個類似的jar包
          (velocity.jar,velocity1-0.8.jar),刪除舊的jar包后,問題解決
          [middlegen] java.lang.IncompatibleClassChangeError
          [middlegen] at [middlegen] at org.apache.velocity.Template.process(Template.java:136)


          2.(評論)關于Many-to-Many需要注意的問題
          比如group/user,user/role,group/role,都是多對多的關系。
          所以有必要搞搞清楚。以group/user為例
          (1)group.getUsers() & user.getGroups()雙向映射。在這里,考慮到user.setGroups()是不會放出來的。所以在user端加入inverse=true,就是說,讓Group端來維護兩者的關系表。
          (2)于是,添加的時候,要把user加入到group的user set中,保存,才有意義!
          (3)如果要刪除group_user的關系,而不是group/user本身,那么,需要在group端設定casade=save-update。否則,group.getUsers().remove(user)不會起作用!
          (4)由于有了FK保護,你是無法單獨刪除User的。同時,由于你指定了inverse=true,所以無法光光的設置user.getGroups().clear就能夠搞定一切。你必須首先在每個Group.getUsers中刪除這個user,才能最后刪除。所以,UserManagerImpl代碼可能看起來像這樣:
          public void delUser(User user) {
          if (user == null) {
          logger.info("Got a null user object!");
          return;
          }
          Session session = null;
          Transaction trans = null;
          boolean bSuccess = false;
          try {
          String username = new String(user.getName());
          session = PLUtils.getSession();
          trans = session.beginTransaction();
          session.update(user);

          Set groups = ((UserEntity)user).getGroups();
          for(Iterator i = groups.iterator();i.hasNext();){
          GroupEntity g = (GroupEntity)i.next();
          session.update(g);
          g.getUsers().remove(user);
          session.update(g);
          }

          // ((UserEntity)user).getGroups().clear();
          session.delete(user);
          bSuccess = true;
          logger.debug("User " + username + " deleted ok!");
          }
          catch (ObjectNotFoundException onfe) {
          logger.info("user not found!", onfe);
          }
          catch (Exception e) {
          logger.error("failed!", e);
          }
          finally {
          try {
          if (bSuccess)
          trans.commit();
          else
          trans.rollback();
          session.close();
          }
          catch (Exception ex) {
          }
          }
          }

          posted on 2007-04-19 15:58 junky 閱讀(787) 評論(0)  編輯  收藏 所屬分類: hibernate

          主站蜘蛛池模板: 阜新市| 白玉县| 阿坝县| 宁陵县| 白银市| 台南县| 建昌县| 伊金霍洛旗| 玉树县| 维西| 广安市| 自贡市| 绥棱县| 万荣县| 临沧市| 确山县| 南京市| 海原县| 马鞍山市| 朔州市| 崇州市| 台北县| 息烽县| 神池县| 芦溪县| 武隆县| 疏附县| 阜平县| 栖霞市| 聂荣县| 花莲县| 双鸭山市| 东平县| 华宁县| 平南县| 定南县| 浙江省| 景谷| 永年县| 绥江县| 来凤县|