Hibernate基于配置文件(九)一对多单向关联映射

本文详细介绍了单向一对多关联在Hibernate框架中的实现方式,包括延迟加载策略、懒加载属性设置以及如何正确地重写hashcode()和equals()方法以避免在HashSet集合中管理对象时引发的问题。同时,文章通过实例展示了如何在测试中验证这些概念的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单向一对多关联


一:group  Set存储contactPerson对象
多:contactPerson

 

在一的一方维护关联关系

一端持有多方的引用,为一个集合,Set集合比较常用

 

单向一对多关联---lazy延迟策略

set集合上可以定义的lazy属性:
    -true 默认
    -false
    -extra --> 除非访问到对象属性,否则不会发出查询对象的具体属性的语句!
              比如,求集合的size(),发出的查询语句时select count(*) 效率高!
              比如,判断集合是否为空,isEmpty(),也不会发出查询属性的select语句!
             
             extra还能改变集合的语义!
             比如Set集合中,判断是否包含需要使用到对象equals() hashcode()
             而使用lazy=extra时,会屏蔽掉JDK语法规定(hibernate使用了一个代理对象)
             原因在于:lazy=extra时,发出的查询语句"不同"!
             Hibernate: select 1 from t_person where gid =? and id =?
            hibernate会根据已有条件,选择一个最高效率能得到结果的查询语句进行执行!

一对多单向关联,在一端维护关系,如HashSet集合,最好重写hashcode()和equals()


在对HashSet集合进行判断时,如contains(),remove()方法的调用,底层都会通过Hashcode()和equals()去判断对象是否相等。如果不重写,在集合中管理对象时时,会引发许多问题。如果不了解底层原因,很难解决。

1.如果id生成策略是hilo或者uuid,在内存中直接生成id值的,则可以只根据id值重写hashcode和equals

2.如果id生成策略是native,依赖数据库生成id值的,则不能使用id值来重写hashcode和equals

例如,在级联保存瞬时对象时,这些瞬时对象都没有id值,在往HashSet集合中添加的时候,根据这两个方法,判断出这些对象都是同一个,导致最后只有1个对象被保存。

 

 

实体类

 

package org.leadfar.hibernate.model;



public class ContactPerson {
	private int id;
	private String name;

	
	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"/>
		
	</class>
	
</hibernate-mapping>

 

 

 

package org.leadfar.hibernate.model;

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

public class Group {
	private int id;
	private String name;
	private Set<ContactPerson> persons;//hibernate约定使用集合的接口类型!
	
	//expert 专家模式
	public void addPerson(ContactPerson person) {
		if(persons == null) {
			persons = new HashSet<ContactPerson>();
		}
		persons.add(person);
	}
	
	public Set<ContactPerson> getPersons() {
		return persons;
	}
	public void setPersons(Set<ContactPerson> persons) {
		this.persons = persons;
	}
	public Group() {
		// TODO Auto-generated constructor stub
	}
	public Group(String name) {
		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;
	}
	
}

 

 

Grasp 强调类的设计原则

GOF 强制类的职责转移

 

 

<?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"/>
		
		  <set name="persons"> 
		  <!-- 对方表中的记录本方的外键字段名为gid -->
		  	<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>

 

 

 

测试

package org.leadfar.hibernate.model;
import java.util.HashSet;
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 extends TestCase {


	public void test_save() 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("朋友");
			//专家模式(grasp)--对外暴露接口,内部封装具体的方法
			g1.addPerson(cp1);//group中有一个集合,存储contactPerson对象
			g1.addPerson(cp2);
			session.save(g1);
			
			Group g2 = new Group("陌生人");
			session.save(g2);
			
			Group g3 = new Group("商务");
			g3.addPerson(cp3);
			session.save(g3);
			
			
			//下面的做法不好!
			/*Set<ContactPerson> persons1 = new HashSet<ContactPerson>();
			persons1.add(cp1);
			persons1.add(cp2);
			
			g1.setPersons(persons1);
			
			Set<ContactPerson> persons2 = new HashSet<ContactPerson>();
			persons2.add(cp3);
			g3.setPersons(persons2);*/
			
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	
	//one-to-many  由一找到多--集合--遍历集合-->多
	public void test_load() throws Exception {
		
		Configuration cfg = new Configuration().configure();
		
		
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		
		Session session = sfactory.openSession();
		
		try {
			
			session.beginTransaction();
			
			Group g = (Group) session.load(Group.class, 1);
			g.getId();
			g.getName();
			
			Set<ContactPerson> persons = g.getPersons();
			for(ContactPerson cp : persons) {
				System.out.println(cp.getId());
				System.out.println(cp.getName());
			}
			
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			
			session.getTransaction().rollback();
		} finally {
			
			session.close();
		}
	}
	
	
	
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值