多对一双向关联
重要属性 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(); } } }
相关推荐
这个压缩包文件“HibernateORM”很可能包含了关于如何在实际项目中设置和使用Hibernate一对多双向关联的示例代码、配置文件或者详细教程。通过学习这些材料,开发者能够深入理解如何在Java应用中利用Hibernate来处理...
“Hibernate 一对多,多对一,一对多双向关联”是指在Java持久化框架Hibernate中,实体间常见的三种关联关系。在数据库设计中,这种关联关系是常见的,例如一个用户可以有多个订单(一对多),一个订单对应一个用户...
"hibernate_many2many_2"这个文件名可能是指一个关于Hibernate多对多关联的示例或教程的第二部分,可能包含配置文件、Java实体类、映射文件以及相关的测试代码。 **详细知识点:** 1. **实体类定义**:在Hibernate...
总结起来,Hibernate中的一对多/多对一关联是通过主外键映射来实现的,通过注解和配置文件定义实体间的关联关系,利用懒加载或立即加载策略控制数据获取,同时要注意双向关联的维护和级联操作的设置,以确保数据的...
在Hibernate中,一对一关联可以通过配置XML映射文件或使用注解来实现。这里我们将使用注解方式进行说明。首先,我们需要在两个实体类中分别定义对应的属性,并使用`@OneToOne`注解来指定关联关系。 1. 实体类A: ``...
- Hibernate通过XML配置文件或注解来设置一对一的关联。在XML配置文件中,我们需要在`<one-to-one>`元素中指定关联的实体和外键字段。在注解方式下,使用`@OneToOne`注解并指定`@JoinColumn`或`@MapsId`。 5. **懒...
在Java持久化框架Hibernate中,一对一双向关联是一种常见的实体关系映射,它反映了数据库中的两个表之间一对一的对应关系。这种关联关系可以是单向的,也可以是双向的,而这里的"hibernate关联关系之一对一双向关联...
“Hibernate ORM - 一对多双向连接表关联关系”这个标题指出我们要讨论的是Hibernate ORM框架中的一种特定数据库关联模型,即一对多的双向关联。在Hibernate中,ORM(对象关系映射)是一种技术,它允许我们用面向...
总之,理解和熟练运用Hibernate的一对多、多对一以及双向关联,是提升Java企业级应用开发效率的关键。通过注解或XML配置,开发者可以灵活地定义实体间的关联,实现数据的持久化。同时,注意级联操作、懒加载策略等...
在提供的压缩包文件`bionetoonetable`中,可能包含了示例代码或者相关的配置文件,用于演示双向一对一基于主键的关联映射的实现。具体的内容需要查看文件才能了解详情。 总结,双向一对一基于主键的关联映射是...
在数据库中,一对一双向关联意味着两个表(或实体类)之间存在一对一的关系,并且双方都可以导航到对方。例如,一个员工可能只属于一个部门,而一个部门也可能只包含一个经理,这样的关系就是一对一双向的。在...
在Hibernate中,一对一关联的配置主要通过注解或XML配置文件完成。对于双向关联,我们需要在两个实体类中分别设置相应的属性和关联注解。 在实体类A中,我们将添加一个类型为B的属性,并使用`@OneToOne`注解来指定...
**描述:** 由于描述为空,我们无法从描述中获取具体的信息,但通常在一对多双向关联中,我们会关注如何在Hibernate配置文件或注解中设置这种关系,以及如何在Java代码中进行操作,如保存、更新和查询等。...
本教程将重点讲解如何在Hibernate中实现多对多双向关联,这是数据库设计中常见的一种关系类型,它允许一个实体实例与多个其他实体实例相互关联。 在数据库设计中,多对多关系意味着一个表的记录可以与另一个表的多...
总结来说,本篇博客主要讲解了如何在MyEclipse中使用Hibernate实现多对一的双向关联,并可能涉及到了一些基本的配置文件和工具使用。对于初学者,理解这些概念和实践步骤是掌握Java Web开发中数据库操作的关键。通过...
在上述配置中,`<one-to-many>`标签定义了`User`到`Order`的一对多关系,而`<many-to-one>`标签定义了`Order`到`User`的多对一关系。`inverse="true"`意味着`Order`端负责维护关系,即当删除一个`Order`时,其对应的...
在Hibernate的一对多关联中,双向关联意味着双方都可以通过导航属性访问对方。例如,用户类(User)可以有一个订单集合(Orders),而订单类(Order)同样有一个用户属性(User)。这样设计的好处在于,我们可以在任一侧轻松...
本篇文章将深入探讨 Hibernate 中的一对多双向关联映射。 在数据库设计中,一对多关联是指一个实体可以与多个其他实体相关联,比如一个学生可以有多个课程,一个部门可以有多名员工。在Hibernate中,这种关系可以...