Hibernate一對多數據關聯

          一對多數據關聯

          一.單向一對多數據關聯
          一個用戶有多個地址,在用戶類TUser中包含地址類TAddress集合。

          1.數據模型

          2.表定義sql
          use sample;

          DROP TABLE T_Address;
          DROP TABLE T_User;

          CREATE TABLE T_User (
                 id 
          INT NOT NULL AUTO_INCREMENT
               , name 
          VARCHAR(50)
               , age 
          INT
               , 
          PRIMARY KEY (id)
          );

          CREATE TABLE T_Address (
                 id 
          INT NOT NULL AUTO_INCREMENT
               , address 
          VARCHAR(200)
               , zipcode 
          VARCHAR(10)
               , tel 
          VARCHAR(20)
               , type 
          VARCHAR(20)
               , 
          user_id INT NOT NULL
               , idx 
          INT
               , 
          PRIMARY KEY (id)
               , 
          INDEX (user_id)
               , 
          CONSTRAINT FK_T_Address_1 FOREIGN KEY (user_id)
                            
          REFERENCES T_User (id)
          );


          3.POJO類
          TUser.java
          package cn.blogjava.start;

          import java.util.Set;

          public class TUser  implements java.io.Serializable {
              
          // Fields    
               private Integer id;
               
          private Integer age;
               
          private String name;
               
          private Set address;


              
          // Constructors

              
          public Integer getAge() {
                  
          return age;
              }

              
          public void setAge(Integer age) {
                  
          this.age = age;
              }


              
          public Set getAddress() {
                  
          return address;
              }

              
          public void setAddress(Set address) {
                  
          this.address = address;
              }

              
          /** default constructor */
              
          public TUser() {
              }
              
              
          /** constructor with id */
              
          public TUser(Integer id) {
                  
          this.id = id;
              }

              
          // Property accessors

              
          public Integer getId() {
                  
          return this.id;
              }
              
              
          public void setId(Integer id) {
                  
          this.id = id;
              }

              
          public String getName() {
                  
          return this.name;
              }
              
              
          public void setName(String name) {
                  
          this.name = name;
              }
          }

          TAddress.java
          package cn.blogjava.start;

          import java.io.Serializable;

          public class TAddress implements Serializable {
              
              
          private Integer id;
              
          private String address;
              
          private String zipcode;
              
          private String tel;
              
          private String type;
              
          private Integer userId;
              
          private Integer idx;
              
              
          public Integer getId() {
                  
          return id;
              }
              
          public void setId(Integer id) {
                  
          this.id = id;
              }
              
          public String getAddress() {
                  
          return address;
              }
              
          public void setAddress(String address) {
                  
          this.address = address;
              }
              
          public Integer getIdx() {
                  
          return idx;
              }
              
          public void setIdx(Integer idx) {
                  
          this.idx = idx;
              }
              
          public String getTel() {
                  
          return tel;
              }
              
          public void setTel(String tel) {
                  
          this.tel = tel;
              }
              
          public String getType() {
                  
          return type;
              }
              
          public void setType(String type) {
                  
          this.type = type;
              }
              
          public Integer getUserId() {
                  
          return userId;
              }
              
          public void setUserId(Integer userId) {
                  
          this.userId = userId;
              }
              
          public String getZipcode() {
                  
          return zipcode;
              }
              
          public void setZipcode(String zipcode) {
                  
          this.zipcode = zipcode;
              }

          }

          3.配置文件
          TUser.hbm.xml
          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping>
              
          <class name="cn.blogjava.start.TUser" table="T_User" catalog="sample"
               dynamic-update
          ="true" dynamic-insert="true"
              
          >
                  
          <id name="id" type="integer">
                      
          <column name="id" />
                      
          <generator class="native" />
                  
          </id>
                  
          <property name="name" type="string" column="name" />
                  
          <property name="age" type="java.lang.Integer" column="age" />

                  
          <set name="address" table="t_address" cascade="all" order-by="zipcode asc">
                      
          <key column="user_id">
                      
          </key>
                      
          <one-to-many class="cn.blogjava.start.TAddress" />
                  
          </set>
              
          </class>
          </hibernate-mapping>

          TAddress.hbm.xml
          注意:沒有配置user_id字段。
          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping>
              
          <class name="cn.blogjava.start.TAddress" table="T_Address" catalog="sample">
                  
          <id name="id" type="integer">
                      
          <column name="id" />
                      
          <generator class="native" />
                  
          </id>
                  
          <property name="address" type="string" column="address" />
                  
          <property name="zipcode" type="string" column="zipcode" />
                  
          <property name="tel" type="string" column="tel" />
                  
          <property name="type" type="string" column="type" />
                  
          <property name="idx" type="java.lang.Integer" column="idx" />
              
          </class>
          </hibernate-mapping>

          4.測試代碼

          package cn.blogjava.start;

          import java.util.HashSet;
          import java.util.Iterator;
          import java.util.List;

          import junit.framework.Assert;
          import junit.framework.TestCase;

          import org.hibernate.HibernateException;
          import org.hibernate.Session;
          import org.hibernate.SessionFactory;
          import org.hibernate.Transaction;
          import org.hibernate.cfg.Configuration;


          public class HibernateTest extends TestCase {
              
              Session session 
          = null;

              
          protected void setUp() {
                  
          try {
                      Configuration config 
          = new Configuration().configure();
                      SessionFactory sessionFactory 
          = config.buildSessionFactory();
                      session 
          = sessionFactory.openSession();
                      
                  } 
          catch (HibernateException e) {
                      e.printStackTrace();
                  }        
              }

              
          protected void tearDown() {
                  
          try {
                      session.close();        
                  } 
          catch (HibernateException e) {
                      e.printStackTrace();
                  }        
              }    
              
              
          /**
               * 對象持久化測試(Insert方法)
               
          */        
              
          public void testInsert() {
                  Transaction tran 
          = null;
                  
          try {
                  
                      TUser user 
          = new TUser();
                      user.setName(
          "byf");
                      user.setAge(
          new Integer(26));
                      
                      TAddress addr 
          = new TAddress();
                      addr.setTel(
          "1123");
                      addr.setZipcode(
          "233123");
                      addr.setAddress(
          "HongKong");
                      
                      TAddress addr2 
          = new TAddress();
                      addr2.setTel(
          "139");
                      addr2.setZipcode(
          "116001");
                      addr2.setAddress(
          "dalian");            

                      TAddress addr3 
          = new TAddress();
                      addr3.setTel(
          "136");
                      addr3.setZipcode(
          "100080");
                      addr3.setAddress(
          "beijing");
                      
                      
          //設置關聯
                      HashSet set = new HashSet();
                      set.add(addr);
                      set.add(addr2);
                      set.add(addr3);
                      user.setAddress(set);
                                             
                      tran 
          = session.beginTransaction();                                
                      
          //插入user信息
                      session.save(user);
                      session.flush();
                      tran.commit();
                      Assert.assertEquals(user.getId().intValue()
          >0 ,true);
                  } 
          catch (HibernateException e) {
                      e.printStackTrace();
                      Assert.fail(e.getMessage());
                      
          if(tran != null) {
                          
          try {
                              tran.rollback();
                          } 
          catch (Exception e1) {
                              e1.printStackTrace();
                          }
                      }
                  }
              }
              
              
          /**
               * 對象讀取測試(Select方法)
               
          */            
              
          public void testSelect(){
                  String hql 
          = " from TUser where name='byf'";
                  
          try {
                      List userList 
          = session.createQuery(hql).list();
                      TUser user 
          = (TUser)userList.get(0);
                      System.out.println(
          "user name is " + user.getName());
                      
                      
          for (Iterator iter = user.getAddress().iterator(); iter.hasNext();) {
                          TAddress addr 
          = (TAddress) iter.next();
                          System.out.println(
          "user address is " + addr.getAddress());                
                      }
                      Assert.assertEquals(user.getName(), 
          "byf");
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                      Assert.fail(e.getMessage());
                  }
              }
          }

          說明:
          一個問題,由于是單向關聯,為了保持關聯關系,我們只能通過主控方對被動方進行級聯更新。如果被關聯方的字段為NOT NULL屬性,當Hibernate創建或者更新關聯關系時,可能出現約束違例。
          例子中T_Address表中的user_id 為NOT NULL,如果在TAddress.hbm.xml映射了全部字段時。創建一個用戶并賦予她地址信息,對于T_Address表而言,hibernate會執行兩條sql語句來保存地址信息。

          要執行兩條SQL語句,是因為關聯是單向的,就是說對于TAddress對象而言,并不知道自己應該與那一個TUser對象關聯,只能先將user_id設為一個空值。
          之后,根據配置文件
                  <set name="address" table="t_address" cascade="all" order-by="zipcode asc">
                      
          <key column="user_id">
                      
          </key>
                      
          <one-to-many class="cn.blogjava.start.TAddress" />
                  
          </set>
          由TUser對象將自身的id賦給addr.user_id,這樣導致addr屬性值變動,在事物提交的時候,會進行update。

          1)當save該用戶的時候,
          insert into t_address  (user_id, address, zipcode, tel) value (null, "HongKong", "233123", "1123")

          2)當tx.commit()時:
          update t_address user_id="1", address="HongKong", zipcode="233123",tel="1123" where id=2;

          這樣,在save user時,就會出現約束違例。

          調整方法:
          可以在定義數據表字段時候,不加NOT NULL約束。或者在開始為user_id隨意賦一個非空值(因為還要update,不正確也沒關系),或者將user_id字段從TAddress.hbm.xml中刪除(本例就是這樣實現)。

          但是這些都是權宜之計,用兩條SQL語句完成一次數據庫操作,性能低下。
          而雙向一對多解決了這個問題。
          下面來實現雙向關聯:
          修改配置文件
          TUser.hbm.xml
          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping>
              
          <class name="cn.blogjava.start.TUser" table="T_User" catalog="sample"
               dynamic-update
          ="true" dynamic-insert="true"
              
          >
                  
          <id name="id" type="integer">
                      
          <column name="id" />
                      
          <generator class="native" />
                  
          </id>
                  
          <property name="name" type="string" column="name" />
                  
          <property name="age" type="java.lang.Integer" column="age" />

                  
          <set 
                      
          name="address" 
                      table
          ="t_address" 
                      inverse
          ="true"
                      cascade
          ="all" 
                      order-by
          ="zipcode asc"
                      
          >
                      
          <key column="user_id">
                      
          </key>
                      
          <one-to-many class="cn.blogjava.start.TAddress" />
                  
          </set>
              
          </class>
          </hibernate-mapping>

          設定inverse="true",表明將TUser類作為被動類,將數據關聯的維護工作交給關聯對象TAddress來管理。
          在one-to-many模型中,將many一方設為主控方有助于性能的改善。(讓總理記住每個人困難,但是每個人記住總理方便)

          TAddress.hbm.xml
          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
          >
          <hibernate-mapping>
              
          <class name="cn.blogjava.start.TAddress" table="T_Address" catalog="sample">
                  
          <id name="id" type="integer">
                      
          <column name="id" />
                      
          <generator class="native" />
                  
          </id>
                  
          <property name="address" type="string" column="address" />
                  
          <property name="zipcode" type="string" column="zipcode" />
                  
          <property name="tel" type="string" column="tel" />
                  
          <property name="type" type="string" column="type" />
                  
          <property name="idx" type="java.lang.Integer" column="idx" />
                  
          <many-to-one
                            
          name="user" 
                            class
          ="cn.blogjava.start.TUser"

                            cascade
          ="none"
                            outer-join
          ="auto"
                            update
          ="true"                  
                            insert
          ="true"

                            access
          ="property"
                            column
          ="user_id"
                            not-null
          ="true"
                  
          />
              
          </class>
          </hibernate-mapping>

          2.對TAddress.java做如下改造:
          去掉user_id字段,增加user字段,和getter,setter方法。
          package cn.blogjava.start;

          import java.io.Serializable;

          public class TAddress implements Serializable {
              
              
          private Integer id;
              
          private String address;
              
          private String zipcode;
              
          private String tel;
              
          private String type;
              
          private Integer idx;
              
          private TUser user;
              
              
          public TUser getUser() {
                  
          return user;
              }
              
          public void setUser(TUser user) {
                  
          this.user = user;
              }
              
          public Integer getId() {
                  
          return id;
              }
              
          public void setId(Integer id) {
                  
          this.id = id;
              }
              
          public String getAddress() {
                  
          return address;
              }
              
          public void setAddress(String address) {
                  
          this.address = address;
              }
              
          public Integer getIdx() {
                  
          return idx;
              }
              
          public void setIdx(Integer idx) {
                  
          this.idx = idx;
              }
              
          public String getTel() {
                  
          return tel;
              }
              
          public void setTel(String tel) {
                  
          this.tel = tel;
              }
              
          public String getType() {
                  
          return type;
              }
              
          public void setType(String type) {
                  
          this.type = type;
              }
              
          public String getZipcode() {
                  
          return zipcode;
              }
              
          public void setZipcode(String zipcode) {
                  
          this.zipcode = zipcode;
              }

          }

          4.測試代碼
          既然TUser不維護關聯關系,需要TAddress需要自己來維護TUser,所以需要addr.setUser(user);
          package cn.blogjava.start;

          import java.util.HashSet;
          import java.util.Iterator;
          import java.util.List;

          import junit.framework.Assert;
          import junit.framework.TestCase;

          import org.hibernate.HibernateException;
          import org.hibernate.Session;
          import org.hibernate.SessionFactory;
          import org.hibernate.Transaction;
          import org.hibernate.cfg.Configuration;


          public class HibernateTest extends TestCase {
              
              Session session 
          = null;

              
          protected void setUp() {
                  
          try {
                      Configuration config 
          = new Configuration().configure();
                      SessionFactory sessionFactory 
          = config.buildSessionFactory();
                      session 
          = sessionFactory.openSession();
                      
                  }
           catch (HibernateException e) {
                      e.printStackTrace();
                  }
                  
              }


              
          protected void tearDown() {
                  
          try {
                      session.close();        
                  }
           catch (HibernateException e) {
                      e.printStackTrace();
                  }
                  
              }
              
              
              
          /**
               * 對象持久化測試(Insert方法)
               
          */
                  
              
          public void testInsert() {
                  Transaction tran 
          = null;
                  
          try {
                  
                      TUser user 
          = new TUser();
                      user.setName(
          "byf");
                      user.setAge(
          new Integer(26));
                      
                      TAddress addr 
          = new TAddress();
                      addr.setTel(
          "1123");
                      addr.setZipcode(
          "233123");
                      addr.setAddress(
          "HongKong");
                      addr.setUser(user);
                      
                      TAddress addr2 
          = new TAddress();
                      addr2.setTel(
          "139");
                      addr2.setZipcode(
          "116001");
                      addr2.setAddress(
          "dalian");       
                      addr2.setUser(user);

                      TAddress addr3 
          = new TAddress();
                      addr3.setTel(
          "136");
                      addr3.setZipcode(
          "100080");
                      addr3.setAddress(
          "beijing");
                      addr3.setUser(user);
                      
                      
          //設置關聯
                      HashSet set = new HashSet();
                      set.add(addr);
                      set.add(addr2);
                      set.add(addr3);
                      user.setAddress(set);
                                             
                      tran 
          = session.beginTransaction();                                
                      
          //插入user信息
                      session.save(user);
                      session.flush();
                      tran.commit();
                      Assert.assertEquals(user.getId().intValue()
          >0 ,true);
                  }
           catch (HibernateException e) {
                      e.printStackTrace();
                      Assert.fail(e.getMessage());
                      
          if(tran != null{
                          
          try {
                              tran.rollback();
                          }
           catch (Exception e1) {
                              e1.printStackTrace();
                          }

                      }

                  }

              }

              
              
          /**
               * 對象讀取測試(Select方法)
               
          */
                      
              
          public void testSelect(){
                  String hql 
          = " from TUser where name='byf'";
                  
          try {
                      List userList 
          = session.createQuery(hql).list();
                      TUser user 
          = (TUser)userList.get(0);
                      System.out.println(
          "user name is " + user.getName());
                      
                      
          for (Iterator iter = user.getAddress().iterator(); iter.hasNext();) {
                          TAddress addr 
          = (TAddress) iter.next();
                          System.out.println(
          "user address is " + addr.getAddress());                
                      }

                      Assert.assertEquals(user.getName(), 
          "byf");
                  }
           catch (Exception e) {
                      e.printStackTrace();
                      Assert.fail(e.getMessage());
                  }

              }

          }

          posted on 2006-07-04 14:45 baim 閱讀(2685) 評論(5)  編輯  收藏 所屬分類: 開源軟件框架

          評論

          # re: Hibernate一對多數據關聯 2008-01-07 19:22 pretender

          很全面,很感謝!!  回復  更多評論   

          # re: Hibernate一對多數據關聯 2008-02-12 18:33 Asmer

          精辟!贊@!!  回復  更多評論   

          # re: Hibernate一對多數據關聯[未登錄] 2008-09-24 20:09 kk

          收藏,推薦
          感激,學習  回復  更多評論   

          # re: Hibernate一對多數據關聯 2009-09-24 14:27 贊你

          簡單就是美  回復  更多評論   

          # re: Hibernate一對多數據關聯 2009-10-20 17:36 很高

          很屁精  回復  更多評論   

          <2009年10月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導航

          常用鏈接

          隨筆分類(27)

          隨筆檔案(28)

          搜索

          最新評論

          主站蜘蛛池模板: 乌苏市| 湘阴县| 宁德市| 龙海市| 临泽县| 潮安县| 旬邑县| 乡城县| 道真| 台东市| 临沧市| 同仁县| 茌平县| 宜都市| 忻州市| 平利县| 连江县| 将乐县| 海晏县| 婺源县| 贵德县| 张家港市| 邹平县| 英超| 许昌市| 宣武区| 丰城市| 海南省| 德江县| 泽州县| 晋城| 铁岭县| 厦门市| 徐汇区| 沂水县| 青田县| 沛县| 青河县| 广汉市| 庆元县| 丰镇市|