淺析Hibernate一對多數(shù)據(jù)關(guān)聯(lián)的問題(一)
Hibernate一對多數(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)
- );
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"?>
- "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" />
- < SPAN>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">
- < SPAN>key>
- <one-to-many class="cn.blogjava.start.TAddress" />
- < SPAN>set>
- < SPAN>class>
- < SPAN>hibernate-mapping>
TAddress.hbm.xml
注意:沒有配置user_id字段。
- xml version="1.0"?>
- "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" />
- < SPAN>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" />
- < SPAN>class>
- < SPAN>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屬性,當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">
- < SPAN>key>
- <one-to-many class="cn.blogjava.start.TAddress" />
- < SPAN>set>
Hibernate一對多數(shù)據(jù)關(guān)聯(lián)是Hibernate中比較典型的問題,這里只是簡單介紹。
【編輯推薦】