Duran's technical life
          踏踏實(shí)實(shí)學(xué)技術(shù),認(rèn)認(rèn)真真做研究。
          Suppose we start with a simple <one-to-many> association from Parent to Child.
           1<hibernate-mapping package="org.hibernate.auction.model">
           2 <class name="Parent" table="PARENT">
           3  <id name="id" column="PARENT_ID" type="long">
           4   <generator class="native"></generator>
           5  </id>
           6  <set name="children">
           7   <key column="MY_PARENT_ID" />
           8   <one-to-many class="org.hibernate.auction.model.Child" />
           9  </set>
          10 </class>
          11 <class name="Child" table="CHILD">
          12  <id name="id" column="CHILD_ID" type="long">
          13   <generator class="native"></generator>
          14  </id>
          15  <property name="name" column="NAME" type="string" />
          16 </class>
          17</hibernate-mapping>

          If we were to execute the following code

           1Parent p = new Parent(new HashSet()); 
           2Child c1 = new Child(new String("c1"
          ));
           3

           4try 
          {
           5    session =
           sessionFactory.openSession();            
           6    tx =
           session.beginTransaction();           
           7
              session.save(p);
           8    Long pid =
           p.getId();
           9
              tx.commit();
          10
              session.close();
          11
              
          12    session =
           sessionFactory.openSession();
          13    tx =
           session.beginTransaction();
          14    Parent pp = (Parent) session.load(Parent.class
          , pid); 
          15
              pp.getChildren().add(c1);        
          16
              session.save(c1);
          17
              session.flush();
          18
              tx.commit();
          19

          20}
           catch (HibernateException e) {
          21}

          Hibernate would issue two SQL statements:
          - an INSERT to create the record for c
          - an UPDATE to create the link from p to c

          Hibernate: insert into PARENT values ( )
          Hibernate: select parent0_.PARENT_ID as PARENT_ID0_ from PARENT parent0_ where parent0_.PARENT_ID=?
          Hibernate: select children0_.MY_PARENT_ID as MY_PAREN3___, children0_.CHILD_ID as CHILD_ID__, children0_.CHILD_ID as CHILD_ID0_, children0_.NAME as NAME0_ from CHILD children0_ where children0_.MY_PARENT_ID=?

          - Hibernate: insert into CHILD (NAME) values (?)
          - Hibernate: update CHILD set MY_PARENT_ID=? where CHILD_ID=?

          This is not only inefficient, but also violates any NOT NULL constraint on the
          MY_PARENT_ID column.

          **********1
          The underlying cause is that the link (the foreign key parent_id) from p to c is not considered part of the state of the Child object and is therefore not created in the INSERT. So the solution is to make the link part of the Child mapping.
          **********1

           <many-to-one name="my_parent"
            class
          ="org.hibernate.auction.model.Parent" column="MY_PARENT_ID"
            not-null
          ="true">
           
          </many-to-one>

          **********2
          Now that the Child entity is managing the state of the link, we tell the collection not to update the link. We use the inverse attribute.
          **********2

           <set name="children" inverse="true">
            
          <key column="MY_PARENT_ID" />
            
          <one-to-many class="org.hibernate.auction.model.Child" />
           
          </set>

          The following code would be used to add a new Child

          1Parent pp = (Parent) session.load(Parent.class, pid); 
          2
          pp.getChildren().add(c1);
          3c1.setMy_parent(pp); //the link is part of the Child object's state. @see***1 

          4session.save(c1);

          And now, only one SQL INSERT would be issued!
          To tighten things up a bit, we could create an addChild() method of Parent.

          1public void addChild(Child c) {
          2  c.setParent(this
          );
          3
            children.add(c);
          4}

          Now, the code to add a Child looks like

          1Parent p = (Parent) session.load(Parent.class, pid);
          2Child c = new
           Child();
          3p.addChild(c);  // 1.let both side of the association knows each other.

          4session.save(c); // 2.save the non-verse side

          =========================================================================================
          CONCLUSION:
          1.The non-inverse(inverse="false") side is responsible to save the in-memory representation (object) to the database .
          --- you should save the child: session.save(c);
          2.Changes made only to the inverse end of the association are not persisted.
          --- you needn't update the parent: //session.update(p);

           1session = sessionFactory.openSession();
           2tx =
           session.beginTransaction();
           3Parent pp = (Parent) session.load(Parent.classnew Long(1
          )); 
           4pp.getChildren().add(c1); //the parent(pp) now knowns about the relationship

           5c1.setMy_parent(pp); //the child(c1) now knows about the relationship
           6

           7//
           when cascade="save-update", update(p) will cause all p's
           8//
           referencing children become persistence(cascade 
           9//
           saveOrUpdate() operation to parent's all children).
          10//
           So, it's same as you explicitly call session.save(c1).
          11

          12//
           when cascade="none"(default), update(p) will just cause
          13//
           p become persistence.
          14//
           And inverse="true", update(p) just persists p, but not 
          15// persists the link between p and c1. @see ***2

          16session.update(pp);  
          17//session.save(c1);  

          18session.flush();
          19
          tx.commit();
          20


          Hibernate: select parent0_.PARENT_ID as PARENT_ID0_ from PARENT parent0_ where parent0_.PARENT_ID=?
          Hibernate: select children0_.MY_PARENT_ID as MY_PAREN3___, children0_.CHILD_ID as CHILD_ID__, children0_.CHILD_ID as CHILD_ID0_, children0_.NAME as NAME0_, children0_.MY_PARENT_ID as MY_PAREN3_0_ from CHILD children0_ where children0_.MY_PARENT_ID=?

           1session = sessionFactory.openSession();
           2tx =
           session.beginTransaction();
           3Parent pp = (Parent) session.load(Parent.classnew Long(1
          )); 
           4
          pp.getChildren().add(c1);
           5
          c1.setMy_parent(pp);
           6//
          session.update(pp);
           7

           8//
           when save(c1), because c1 holds a reference to its Parent
           9// (my_parent), so p become persistence too.

          10session.save(c1);  //The relationship will be saved. @see ***1
          11session.flush();
          12
          tx.commit();
          13


          Hibernate: select parent0_.PARENT_ID as PARENT_ID0_ from PARENT parent0_ where parent0_.PARENT_ID=?
          Hibernate: select children0_.MY_PARENT_ID as MY_PAREN3___, children0_.CHILD_ID as CHILD_ID__, children0_.CHILD_ID as CHILD_ID0_, children0_.NAME as NAME0_, children0_.MY_PARENT_ID as MY_PAREN3_0_ from CHILD children0_ where children0_.MY_PARENT_ID=?
          Hibernate: insert into CHILD (NAME, MY_PARENT_ID) values (?, ?)


           

          posted on 2005-05-19 09:28 Duran's technical life 閱讀(586) 評(píng)論(0)  編輯  收藏 所屬分類: 技術(shù)積累
           
          主站蜘蛛池模板: 泽库县| 黄冈市| 济南市| 凌海市| 武胜县| 色达县| 芦山县| 安宁市| 南汇区| 蕲春县| 凤凰县| 邓州市| 平南县| 昌宁县| 花莲县| 和顺县| 伊吾县| 西盟| 翁源县| 万宁市| 德惠市| 杂多县| 吉水县| 凤山市| 明溪县| 珲春市| 望都县| 河源市| 满洲里市| 蓬溪县| 横峰县| 资阳市| 谢通门县| 文登市| 武隆县| 兴隆县| 武强县| 扶余县| 登封市| 长宁县| 邵阳县|