`
schy_hqh
  • 浏览: 556026 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

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();
		}
	}
	
	
	
}

 

分享到:
评论

相关推荐

    Hibernate ORM - 一对多双向关联关系

    这个压缩包文件“HibernateORM”很可能包含了关于如何在实际项目中设置和使用Hibernate一对多双向关联的示例代码、配置文件或者详细教程。通过学习这些材料,开发者能够深入理解如何在Java应用中利用Hibernate来处理...

    hibernate一对多,多对一,一对多双向关联

    “Hibernate 一对多,多对一,一对多双向关联”是指在Java持久化框架Hibernate中,实体间常见的三种关联关系。在数据库设计中,这种关联关系是常见的,例如一个用户可以有多个订单(一对多),一个订单对应一个用户...

    hibernate多对多双向关联

    "hibernate_many2many_2"这个文件名可能是指一个关于Hibernate多对多关联的示例或教程的第二部分,可能包含配置文件、Java实体类、映射文件以及相关的测试代码。 **详细知识点:** 1. **实体类定义**:在Hibernate...

    hibernate基于主外键的一对多/多对一关联

    总结起来,Hibernate中的一对多/多对一关联是通过主外键映射来实现的,通过注解和配置文件定义实体间的关联关系,利用懒加载或立即加载策略控制数据获取,同时要注意双向关联的维护和级联操作的设置,以确保数据的...

    Hibernate一对一唯一外键关联映射(双向关联)

    在Hibernate中,一对一关联可以通过配置XML映射文件或使用注解来实现。这里我们将使用注解方式进行说明。首先,我们需要在两个实体类中分别定义对应的属性,并使用`@OneToOne`注解来指定关联关系。 1. 实体类A: ``...

    hibernate一对一之唯一外键关联(双向关联)

    - Hibernate通过XML配置文件或注解来设置一对一的关联。在XML配置文件中,我们需要在`&lt;one-to-one&gt;`元素中指定关联的实体和外键字段。在注解方式下,使用`@OneToOne`注解并指定`@JoinColumn`或`@MapsId`。 5. **懒...

    hibernate关联关系之一对一双向关联

    在Java持久化框架Hibernate中,一对一双向关联是一种常见的实体关系映射,它反映了数据库中的两个表之间一对一的对应关系。这种关联关系可以是单向的,也可以是双向的,而这里的"hibernate关联关系之一对一双向关联...

    Hibernate ORM - 一对多双向连接表关联关系

    “Hibernate ORM - 一对多双向连接表关联关系”这个标题指出我们要讨论的是Hibernate ORM框架中的一种特定数据库关联模型,即一对多的双向关联。在Hibernate中,ORM(对象关系映射)是一种技术,它允许我们用面向...

    Hibernate一对多(多对一)双向关联(annotation/xml)

    总之,理解和熟练运用Hibernate的一对多、多对一以及双向关联,是提升Java企业级应用开发效率的关键。通过注解或XML配置,开发者可以灵活地定义实体间的关联,实现数据的持久化。同时,注意级联操作、懒加载策略等...

    hibernate 双向一对一基于主键的关联映射

    在提供的压缩包文件`bionetoonetable`中,可能包含了示例代码或者相关的配置文件,用于演示双向一对一基于主键的关联映射的实现。具体的内容需要查看文件才能了解详情。 总结,双向一对一基于主键的关联映射是...

    Hibernate教程07_关系映射之一对一双向主键关联

    在数据库中,一对一双向关联意味着两个表(或实体类)之间存在一对一的关系,并且双方都可以导航到对方。例如,一个员工可能只属于一个部门,而一个部门也可能只包含一个经理,这样的关系就是一对一双向的。在...

    Hibernate教程05_关系映射之一对一双向外键关联

    在Hibernate中,一对一关联的配置主要通过注解或XML配置文件完成。对于双向关联,我们需要在两个实体类中分别设置相应的属性和关联注解。 在实体类A中,我们将添加一个类型为B的属性,并使用`@OneToOne`注解来指定...

    Hibernate ORM - 一对多双向组合关联关系

    **描述:** 由于描述为空,我们无法从描述中获取具体的信息,但通常在一对多双向关联中,我们会关注如何在Hibernate配置文件或注解中设置这种关系,以及如何在Java代码中进行操作,如保存、更新和查询等。...

    Hibernate教程14_关系映射之多对多双向关联

    本教程将重点讲解如何在Hibernate中实现多对多双向关联,这是数据库设计中常见的一种关系类型,它允许一个实体实例与多个其他实体实例相互关联。 在数据库设计中,多对多关系意味着一个表的记录可以与另一个表的多...

    myeclipse试用小记----Hibernate多对一双向关联(2)

    总结来说,本篇博客主要讲解了如何在MyEclipse中使用Hibernate实现多对一的双向关联,并可能涉及到了一些基本的配置文件和工具使用。对于初学者,理解这些概念和实践步骤是掌握Java Web开发中数据库操作的关键。通过...

    hibernate双向一对多关联映射(XML)

    在上述配置中,`&lt;one-to-many&gt;`标签定义了`User`到`Order`的一对多关系,而`&lt;many-to-one&gt;`标签定义了`Order`到`User`的多对一关系。`inverse="true"`意味着`Order`端负责维护关系,即当删除一个`Order`时,其对应的...

    hibernate一对多关联映射(双向关联)

    在Hibernate的一对多关联中,双向关联意味着双方都可以通过导航属性访问对方。例如,用户类(User)可以有一个订单集合(Orders),而订单类(Order)同样有一个用户属性(User)。这样设计的好处在于,我们可以在任一侧轻松...

    hibernate对映射xml的一对多的双向关联详解

    本篇文章将深入探讨 Hibernate 中的一对多双向关联映射。 在数据库设计中,一对多关联是指一个实体可以与多个其他实体相关联,比如一个学生可以有多个课程,一个部门可以有多名员工。在Hibernate中,这种关系可以...

Global site tag (gtag.js) - Google Analytics