Hibernate基于配置文件(十)多对一双向关联

多对一双向关联

 

重要属性 inverse=true

作用:

强制在多的那端维护关联,避免在一的一端对集合操作出现问题,因为操纵集合维护关系有很多注意事项,一不留神就会出现问题!

设置inverse=true后,对集合进行操作,不会对关联进行设置

比如,对一端的内容进行修改,不管怎么改,关联关系仍然存在,因为强制由多端去维护!

inverse=true,不影响查询(从一端获取集合中的对象完全没问题)

inverse=true,如果通过一端的集合来保存对方,虽然对象都能够映射到数据库中,但是会造成关联的丢失,因为一端不维护关联。

 

多对一双向关联

1.配置文件的正确配置(双方的关联字段必须一致!都是gid)

ContactPerson类的配置文件

<hibernate-mapping
    package="org.hibernate.auction">
    <!-- name为实体类 table为映射到数据库中的表  lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)-->
    <class name="org.leadfar.hibernate.model.ContactPerson" table="t_person" >
        <!-- id为数据库标识,作为主键 -->
        <id name="id">
            <generator class="native"/>
        </id>
       
        <property name="name"/>
        <many-to-one name="group" column="gid"> </many-to-one>
    </class>
       
</hibernate-mapping>



Group类的配置文件

<hibernate-mapping
    package="org.hibernate.auction">
    <!-- name为实体类 table为映射到数据库中的表  lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)-->
    <class name="org.leadfar.hibernate.model.Group" table="t_group" >
        <!-- id为数据库标识,作为主键 -->
        <id name="id">
            <generator class="native"/>
        </id>
       
        <property name="name"/>
       
          <set name="persons" lazy="true">
              <key column="gid"></key>
             
              <!-- class说明多的一方为:org.leadfar.hibernate.model.ContactPerson -->
              <one-to-many class="org.leadfar.hibernate.model.ContactPerson"></one-to-many>
          </set>
       
    </class>
   
</hibernate-mapping>

2.可以从任意一方获取到对方的信息

3.集合类型维护关联关系时,使用业务主键复写hashcode和equals(组合关系时才在一的一端维护关联)

4.多数情况下强制约定在多的一方维护关联关系,而不在一的那方维护关系(防止更新一的一方时,多的那方的外键丢失)!!!

5.inverse=true 强制在多的一端维护关联

 

 

 

实体类

 

package org.leadfar.hibernate.model;



public class ContactPerson {
	private int id;
	private String name;
	//一端的引用/关联的名称
	private Group group;
	
	
	
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ContactPerson other = (ContactPerson) obj;
		if (id != other.id)
			return false;
		return true;
	}
	public ContactPerson() {
		// TODO Auto-generated constructor stub
	}
	public ContactPerson(String name) {
		// TODO Auto-generated constructor stub
		this.name = name;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	
	
}

 

<?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="org.hibernate.auction">
	<!-- name为实体类 table为映射到数据库中的表  lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)-->
	<class name="org.leadfar.hibernate.model.Group" table="t_group" >
		<!-- id为数据库标识,作为主键 -->
		<id name="id">
			<generator class="native"/>
		</id>
		
		<property name="name"/>
			<!-- 
			inverse 默认为false . inverse=true 强制在多的一端维护两者间的关联 
			inverse只能用在一对多双向关联中使用
			lazy控制hibernate查询语句的发出
			inverse=true,hibernate对集合不进行管理,这时就强制开发人员从多的一端取维护关系了!
			因为双方使用的都是gid字段,所以多的一端建立好关联后,一的一端也能通过gid来获取关联记录
			-->
		  <set name="persons" lazy="extra" inverse="true"> 
		  	<key column="gid"></key> <!--双方需保持字段名一致column="gid"-->
		  	<!-- class说明多的一方为:org.leadfar.hibernate.model.ContactPerson -->
		  	<one-to-many class="org.leadfar.hibernate.model.ContactPerson"></one-to-many>
		  </set>
		
	</class>
	
</hibernate-mapping>

 

package org.leadfar.hibernate.model;



public class ContactPerson {
	private int id;
	private String name;
	//一端的引用/关联的名称
	private Group group;
	
	
	
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ContactPerson other = (ContactPerson) obj;
		if (id != other.id)
			return false;
		return true;
	}
	public ContactPerson() {
		// TODO Auto-generated constructor stub
	}
	public ContactPerson(String name) {
		// TODO Auto-generated constructor stub
		this.name = name;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	
	
}

 

<?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="org.hibernate.auction">
	<!-- name为实体类 table为映射到数据库中的表  lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)-->
	<class name="org.leadfar.hibernate.model.ContactPerson" table="t_person" >
		<!-- id为数据库标识,作为主键 -->
		<id name="id">
			<generator class="native"/>
		</id>
		
		<property name="name"/>
		<!--双方需保持字段名一致column="gid"-->
		<many-to-one name="group" column="gid"> </many-to-one>
	</class>
		
</hibernate-mapping>

 

测试

package org.leadfar.hibernate.model;
import java.util.Iterator;
import java.util.Set;

import junit.framework.TestCase;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test_one2Many_01_bidirection extends TestCase {


	//双向关联保存对象的第一种方式:
	//一的一方使用集合保存关联关系
	//(操纵集合来维护关系比较麻烦,除非组合关系时才使用)
	//所以,一般都是在多的一方维护关系!
	public void test_save01() throws Exception {
		
		Configuration cfg = new Configuration().configure();
		
		
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		
		Session session = sfactory.openSession();
		
		try {
			
			session.beginTransaction();
			
			ContactPerson cp1 = new ContactPerson("张学友");
			session.save(cp1);
			ContactPerson cp2 = new ContactPerson("郑伊健");
			session.save(cp2);
			ContactPerson cp3 = new ContactPerson("郭富城");
			session.save(cp3);
			
			Group g1 = new Group("朋友");
			g1.addPerson(cp1);//将多的那方的对象存入集合
			g1.addPerson(cp2);//将多的那方的对象存入集合
			session.save(g1);
			
			Group g2 = new Group("商务");
			session.save(g2);
			
			Group g3 = new Group("陌生人");
			g3.addPerson(cp3);//将多的那方的对象存入集合
			session.save(g3);

			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	
	//双向关联保存对象的第二种方式:
	//多的一方保存关联关系
	//从多的一方维护双方关系比较方便,比操纵集合更不容易出错
	//推荐从多的一方来建立并维护关系,除非组合关系出现时才在一的一方维护关系~
	public void test_save02() throws Exception {
		
		Configuration cfg = new Configuration().configure();
		
		
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		
		Session session = sfactory.openSession();
		
		try {
			
			session.beginTransaction();
			
			
			Group g1 = new Group("朋友");
			session.save(g1);
			
			Group g2 = new Group("商务");
			session.save(g2);
			
			Group g3 = new Group("陌生人");
			session.save(g3);
			
			ContactPerson cp1 = new ContactPerson("张学友");
			cp1.setGroup(g1);
			session.save(cp1);
			
			ContactPerson cp2 = new ContactPerson("郑伊健");
			cp2.setGroup(g2);
			session.save(cp2);
			
			ContactPerson cp3 = new ContactPerson("郭富城");
			cp3.setGroup(g3);
			session.save(cp3);
			
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	
	
	public void test_load01() throws Exception {
		
		Configuration cfg = new Configuration().configure();
		
		
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		
		Session session = sfactory.openSession();
		
		try {
			
			session.beginTransaction();
			
			//双方都建立了与对方的关联
			//从Group---获取ContactPerson
			Group g = (Group) session.load(Group.class, 1);
			
			Set<ContactPerson> persons = g.getPersons();
			Iterator<ContactPerson> it = persons.iterator();
			while(it.hasNext()) {
				ContactPerson p = it.next();
				System.out.println(p.getId()+","+p.getName());
			}
			
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	public void test_load02() throws Exception {
		
		Configuration cfg = new Configuration().configure();
		
		
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		
		Session session = sfactory.openSession();
		
		try {
			
			session.beginTransaction();
			
			//双方都建立了与对方的关联
			//从ContactPerson---获取Group
			ContactPerson cp = (ContactPerson) session.load(ContactPerson.class, 3);
			
			Group g = cp.getGroup();
			
			System.out.println(g.getId()+","+g.getName());
			
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	
	//多对一双向关联时,如果更新一的一方,将造成多的一方外键丢失,被置为了NULL
	public void test_update01() throws Exception {
		
		Configuration cfg = new Configuration().configure();
		
		
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		
		Session session = sfactory.openSession();
		
		try {
			
			session.beginTransaction();
			/*
			模拟页面中传递参数过来,修改组名
			struts2自动创建一个Group对象
			然后更新组名---结果是,子表外键丢失,被置为了NULL
			Hibernate: update t_group set name=? where id=?
			Hibernate: update t_person set gid=null where gid=?
			相当于清空了Group中id为1的persons集合中的内容
			所以会导致Group对象与ContactPerson对象之间的关联关系丢失!
			
			当使用了inverse=true属性时,就能避免这种现象发生
			1.从一的一端添加对象到集合中,将导致无法创建外键---强制从多的一端取建立连接
			2.从多的一端建立连接,就能保证更新group时,不发生外键丢失!
			3.所以,在多对一双向关联时,使用inverse=true,可以防止很多麻烦事情的发生!
			*/
			Group g = new Group("新的Group");
			g.setId(1);
			
			session.update(g);
			
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	
	
	
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值