zoukankan      html  css  js  c++  java
  • Hibernate一对多数据关联(zz)

    一对多数据关联

    一.单向一对多数据关联
    一个用户有多个地址,在用户类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());
            }

        }

    }
  • 相关阅读:
    【C++】基础及引用
    gradle打包分编译环境
    gradle
    MediaPlayer滑动不准的问题
    python初步入门
    音频播放服务
    《深入理解Android2》读书笔记(二)
    缓存(LruCache)机制
    handler机制
    监听网络状态
  • 原文地址:https://www.cnblogs.com/batys/p/2391278.html
Copyright © 2011-2022 走看看