hiberenat 集合映射中many-to-one的用法

今天学习了hibernate集合映射中many-to-one的用法,现将一些体会写下来。

还是采用教程中的例子:两个实体类person和Address

package eg;

public class Person{

    	private Long id;
    	private Address address;	
    	public Person() {

    	}
    	public Long getId(){
    		return this.id;
    	}

    	private void setId(Long id){
		this.id = id;
    	}
	public void setAddress(Address address){
		this.address = address;
	}
	public Address getAddress(){
		return this.address;
	}
}
 
package eg;
import java.util.*;
public class Address{
    private Long addressId;
    private List people = new ArrayList();
    public Address(){}
    public Long getId(){
    	return this.addressId;
    }
    private void setId(Long addressId){
	this.addressId = addressId;
    }
	public void setPeople(List people){
		this.people = people;
	}
	public List getPeople(){
		return this.people;
	}

}

 映射文件:Person.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 package="eg">

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address"
	 class="Address" 
        column="addressId"
        not-null="true"
	 insert="false"
        update="false"
	/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <list name="people" inverse="false" lazy="true" cascade="all"> 
	<key column="addressId" not-null="true"/>
	<list-index column="peopleidx" base="0"/>
	<one-to-many class="Person" />
    </list>	
</class>
</hibernate-mapping>

 测试代码:

package eg;
import org.hibernate.Session;
import org.hibernate.impl.SessionImpl;
import org.hibernate.Hibernate;
import java.util.*;
import org.hibernate.tutorial.util.HibernateUtil;

public class Manager {

    public static void main(String[] args) throws Throwable{
        Manager mgr = new Manager();

        if (args[0].equals("store")) {
            mgr.createAndStorePerson();
        }else if (args[0].equals("storel")) {
            mgr.createAndStorePerson(3L);
        }else if (args[0].equals("loadA")) {
            
	    List s = mgr.loadAddress(3L);
        }



        HibernateUtil.getSessionFactory().close();
    }
    private Long createAndStorePerson(){
	Session session = HibernateUtil.getSessionFactory().getCurrentSession();
       session.beginTransaction();

	Person p = new Person();
	Address a = new Address();
	p.setAddress(a);
	Integer i = 	Integer.valueOf(new Random().nextInt(20));
	a.getPeople().add(p);
	session.save(a);
	
       session.getTransaction().commit();
	return p.getId();
   }
    private void createAndStorePerson(Long l){
	Session session = HibernateUtil.getSessionFactory().getCurrentSession();
       session.beginTransaction();

	Person p = new Person();
	Address a = (Address)session.load(Address.class,l);
	a.getPeople().add(p);
	p.setAddress(a);	
	session.save(a);
	
       session.getTransaction().commit();

   }

    private List loadAddress(Long l) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();	
	 Address a = (Address)session.load(Address.class,l);
	 List s = a.getPeople();
	 Hibernate.initialize(s);
        session.getTransaction().commit();
        return s;
   }
}
 

在整个测试的过程中有几点需要记住:

1、单向映射时:只在多端声明many-to-one即可单端不用知道映射,也只在多端维护关系。

<many-to-one name="address" 
        column="addressId"
        not-null="true"/>

 如上面的address是指向实体类Person中引用的实体对象address,在程序中通过设定对Address实体的引用而建立关系的。

       Person p = new Person();
	Address a = new Address();
	p.setAddress(a);
	session.save(a);

 2、双向映射时,须在两端设置,也要让单端知道关系,而哪一端来维护关系要看具体的情形。一般情况下,单端要通过一个集合来引用对应的多端实体对象。可用的集合有map、set、list、array、bag、idbag.

     Hibernate要求持久化集合值字段必须声明为接口。

private List people = new ArrayList();

 

实际的接口可能是java.util.Set , java.util.Collection , java.util.List , java.util.Map , java.util.SortedSet , java.util.SortedMap 或者...任何你喜欢的类型!("任何你喜欢的类型" 代表你需要编写 org.hibernate.usertype.UserCollectionType 的实现.)

注意我们是如何用一个HashSet 实例来初始化实例变量的.这是用于初始化新创建(尚未持久化)的类实例中集合值属性的最佳方法。当你持久化这个实例时——比如通过调用persist() ——Hibernate 会自动把HashSet 替换为Hibernate自己的Set 实现。

根据不同的接口类型,被Hibernate注射的持久化集合类的表现类似HashMap , HashSet , TreeMap , TreeSet or ArrayList

集合类实例具有值类型的通常行为。当被持久化对象引用后,他们会自动被持久化,当不再被引用后,自动被删除。假若实例被从一个持久化对象传递到另一个,它 的元素可能从一个表转移到另一个表。两个实体不能共享同一个集合类实例的引用。因为底层关系数据库模型的原因,集合值属性无法支持空值语 义;Hibernate对空的集合引用和空集合不加区别。

 如果你使用List (或者其他有序集合类),你需要设置外键对应的key 列为 not null 假若集合映射的<key> 元素对应的底层外键字段是NOT NULL 的,那么为这一key元素定义not-null="true" 是很重要的。不要仅仅为可能的嵌套<column> 元素定义not-null="true"<key> 元素也是需要的。 ),让Hibernate来从集合端管理关联,维护每个元素的索引(通过设置update="false" and insert="false" 来对另一端反向操作)。同时由于list要在多端维护一个索引列,所以list映射应该设为在集合端具有inverse="false" cascade="save-update"属性。 通过list-index指定的索引字段所起的作用是保证list中可同时出现多个相同的外关键值,当hebernate自动维护索引时,只有在产生了多值的情况下才增加索引值。刚开始测试时不知道这点,见其值一直是0(没有产生多对一的值)还以为没有配合适,浪费了好多时间。这种情况下关系的维护应在集合端。

 

       Person p = new Person();
	Address a = new Address();
	p.setAddress(a);
	a.getPeople().add(p);
	session.save(a);

但是相同的设置在换成array后只能存储实体值,list-index字段的值却不能自动生成,不知道在哪里解决。真是好像看懂了,拿到手里就傻了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值