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之間關係。多對多關聯中,在哪一方維護關聯關係都可以。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章