一對多數(shù)據(jù)關(guān)聯(lián)

          一.單向一對多數(shù)據(jù)關(guān)聯(lián)
          一個用戶有多個地址,在用戶類TUser中包含地址類TAddress集合。

          1.數(shù)據(jù)模型

          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");
          ????????????
          ????????????
          //設(shè)置關(guān)聯(lián)
          ????????????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());
          ????????}
          ????}
          }

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

          要執(zhí)行兩條SQL語句,是因為關(guān)聯(lián)是單向的,就是說對于TAddress對象而言,并不知道自己應(yīng)該與那一個TUser對象關(guān)聯(lián),只能先將user_id設(shè)為一個空值。
          之后,根據(jù)配置文件
          ????????<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,這樣導(dǎo)致addr屬性值變動,在事物提交的時候,會進行update。

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

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

          這樣,在save user時,就會出現(xiàn)約束違例。

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

          但是這些都是權(quán)宜之計,用兩條SQL語句完成一次數(shù)據(jù)庫操作,性能低下。
          而雙向一對多解決了這個問題。
          下面來實現(xiàn)雙向關(guān)聯(lián):
          修改配置文件
          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>

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

          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不維護關(guān)聯(lián)關(guān)系,需要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);
          ????????????
          ????????????
          //設(shè)置關(guān)聯(lián)
          ????????????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 閱讀(557) 評論(1)  編輯  收藏 所屬分類: ORM:Hibernate及其他
          主站蜘蛛池模板: 峡江县| 廉江市| 黄石市| 彩票| 确山县| 四川省| 双峰县| 罗甸县| 夏津县| 辰溪县| 东阿县| 正蓝旗| 旺苍县| 海宁市| 台东县| 城口县| 巴彦县| 西乡县| 依安县| 弥勒县| 玉龙| 潍坊市| 沐川县| 尼勒克县| 嘉荫县| 桐梓县| 南投县| 阿尔山市| 宁津县| 洛宁县| 石门县| 广元市| 阿坝县| 邹城市| 长顺县| 社旗县| 龙井市| 宁陕县| 保靖县| 乌拉特中旗| 望奎县|