hibernate关联关系笔记

hibernate中的关联关系分为多对一关联,一对一关联和多对多关联。这几种关联关系很容易弄错,索性就记录在博客里。

一、多对一关联

多对一是最常见的关联关系,我们以QQ中的联系人(ContactPerson)和分组(Group)为例说明。ContactPerson与Group是多对一关系。

1.实体类

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

package com.lql.demo;

import java.util.HashSet;
import java.util.Set;

public class Group {

	private int id;
	private String name;
	private Set<ContactPerson> persons;
	
	public void addPerson(ContactPerson person){
		if(persons == null){
			persons = new HashSet<ContactPerson>();
		}
		persons.add(person);
	}
	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;
	}
	public Set<ContactPerson> getPersons() {
		return persons;
	}
	public void setPersons(Set<ContactPerson> persons) {
		this.persons = persons;
	}
	
	
}

需要注意一点:在ContactPerson中保存的是一个Group对象的引用,而不是groupId,但是数据库表中保存的是groupId(引用的是group的id),因为Hibernate是这样来设计的。如果ContactPerson中引用的是groupId,映射文件直接用<property name=”groupId”>即可,这样也就没有多对一联系。多对一联系中,查询时如果没有用到引用,Hibernate是不会发出查询的,只有当用到引用,hibernate才会发出查询语句

多对一的懒加载模式有proxy和false,no-proxy三种,proxy也就相当于true,no-proxy基本上不用


2、映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	
	<!--ContactPerson 映射文件 -->
	
<hibernate-mapping 
	package="com.lql.demo">

	<class name="ContactPerson" table="tb_contact" lazy="true">
		<comment>Users may bid for or sell auction items.</comment>
		
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" ></property>
		<many-to-one name="group" column="groupid"></many-to-one>
	</class>
	
</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

	<!-- Group映射文件 -->

<hibernate-mapping package="com.lql.demo">

	<class name="Group" table="tb_group" lazy="true">
		<comment>Users may bid for or sell auction items.</comment>

		<id name="id">
			<generator class="native" />
		</id>
		<property name="name"></property>


		<!--
			多对一联系,集合名为Group中persons key是在一的那张表里加一个字段groupid 在双向关联的中如果在某一方的关联配置中指定
			inverse=”true” ,那么本方就不能维护两者之间的关联关系。关联关系就由对方一方来维护。Inverse
			默认是false,双方都可以维护关联关系。维护关联关系的意思是可以再本方的对象中保存对方的引用。
			extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据
		-->
		<set name="persons" order-by="id desc" lazy="extra" inverse="true">
			<key column="groupid"></key>
			<one-to-many class="com.lql.demo.ContactPerson" />
		</set>

	</class>

</hibernate-mapping>


group表

ContactPerson表


二、一对一联系

以人(Person)和身份证(IDCard)之间的关系为例,每个人和身份证的关系都是一对一的

1.实体类

package com.lql.demo;

public class Person {

	private int id;
	private String name;
	private String address;
	private IdCard idCard;
	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;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public IdCard getIdCard() {
		return idCard;
	}
	public void setIdCard(IdCard idCard) {
		this.idCard = idCard;
	}
	
}

package com.lql.demo;

public class IdCard {

	private int id;
	private String idCardNum;
	private Person person;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getIdCardNum() {
		return idCardNum;
	}
	public void setIdCardNum(String idCardNum) {
		this.idCardNum = idCardNum;
	}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
	
}

2.映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	
	<!-- Person映射文件 -->
	
<hibernate-mapping 
	package="com.lql.demo">

	<class name="Person" table="tb_person" lazy="true">
		<comment>Users may bid for or sell auction items.</comment>
		
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" ></property>
		<property name="address"></property>
		<one-to-one name="idCard"></one-to-one>
	</class>
	
</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	
	<!-- IdCard映射文件 -->
	
<hibernate-mapping 
	package="com.lql.demo">

	<class name="IdCard" table="tb_idcard" lazy="true">
		<comment>Users may bid for or sell auction items.</comment>
		
		<id name="id">
			<generator class="foreign">
			<param name="property">person</param>
			</generator>
		</id>
		<property name="idCardNum" ></property>
		<one-to-one name="person" constrained="true"></one-to-one>
	</class>
	
</hibernate-mapping>

IdCard表中的id会依赖与Person表中的id,并与其保持一致。

constrained只能在one-to-one的映射中使用,(一般在主表的映射中,有外键的那个表)。如果constrained=true, 则表明存在外键与关联表对应,并且关联表中肯定存在对应的键与其对应, 另外该选项最关键的是影响save和delete的先后顺序。例如增加的时候,如果constainted=true,则会先增加关联表,然后增加本表。 删除的时候反之。

               Person person = new Person();//先生成

                 person.setName("狗蛋");

                 person.setAddress("北京");

                 session.save(person);

                

                 IdCard idCard = new IdCard();//后生成

                 idCard.setIdCardNum("123213213122313");

                 idCard.setPerson(person);

                 session.save(idCard);

注意如果将idCard.setPerson(person);改成person.setIdCard(idcard);就发产生异常

因为在配置映射的时候,Person的id是自动生成的, IdCard是依赖于Person的Id的,这里要特别注意。

Person表


IdCard表


三、多对多关联

这里以角色(role)和人(Person)来说明,一个人可以有多个角色(公司职员,丈夫,儿子等),一个角色也可以有多个人。所以角色和人是多对多的关系。

package com.lql.m2m;

import java.util.HashSet;
import java.util.Set;

public class Person2 {

	private int id;
	private String name;
	private Set<Role> roles;
	
	public void addRoleToPerson(Role role){
		if(roles == null){
			roles = new HashSet<Role>();
		}
		roles.add(role);
	}
	
	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;
	}
	public Set<Role> getRoles() {
		return roles;
	}
	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}
	
}

package com.lql.m2m;

import java.util.HashSet;
import java.util.Set;

public class Role {

	private int id;
	private String name;
	private Set<Person2> persons;
	
	public void addPersonToRole(Person2 person){
		if(persons == null){
			persons = new HashSet<Person2>();
		}
		persons.add(person);
	}
	
	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;
	}
	public Set<Person2> getPersons() {
		return persons;
	}
	public void setPersons(Set<Person2> persons) {
		this.persons = persons;
	}
	
	
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

	<!-- Role映射文件 -->

<hibernate-mapping package="com.lql.m2m">

	<class name="Role" table="tb_role" lazy="true">
		<comment>Users may bid for or sell auction items.</comment>

		<id name="id">
			<generator class="native" />
		</id>
		<property name="name" ></property>
		
		
		 <set name="persons" table="tb_person_role" lazy="extra">
		 	<key column="roleid" ></key>
		 	<many-to-many class="com.lql.m2m.Person2" column="personid"/>
		 </set>    
		
	</class>

</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

	<!-- Person2映射文件 -->

<hibernate-mapping package="com.lql.m2m">

	<class name="Person2" table="tb_person2" lazy="true">
		<comment>Users may bid for or sell auction items.</comment>

		<id name="id">
			<generator class="native" />
		</id>
		<property name="name" ></property>
	
		 <set name="roles" table="tb_person_role" lazy="extra">
		 	<key column="personid" ></key>
		 	<many-to-many class="com.lql.m2m.Role" column="roleid"/>
		 </set>    
		
	</class>

</hibernate-mapping>

多对多关联会单独生成一张,关联关系表。


这个表中保存的是,角色与Person之间关系。多对多关联中,在哪一方维护关联关系都可以。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值