一對多數據關聯

          一.單向一對多數據關聯
          一個用戶有多個地址,在用戶類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-05 15:13 knowhow 閱讀(558) 評論(1)  編輯  收藏 所屬分類: ORM:Hibernate及其他
          主站蜘蛛池模板: 莫力| 文成县| 乐至县| 哈尔滨市| 江安县| 裕民县| 柞水县| 琼结县| 永仁县| 宜都市| 义马市| 伊金霍洛旗| 山丹县| 沙坪坝区| 海盐县| 江华| 聊城市| 西宁市| 襄城县| 阿图什市| 枣庄市| 朝阳区| 江西省| 凤庆县| 延寿县| 屯昌县| 安康市| 龙游县| 安阳市| 海口市| 蒙自县| 南岸区| 渝中区| 荣昌县| 札达县| 贵州省| 文成县| 西藏| 玉林市| 九江县| 女性|