超详细的Hibernate关联关系之双向的一对多关联关系的CRUD操作————学习至黑马程序员****

说明:

1.这里是使用  客户-联系人  来做这个双向一对多关联映射的。即,一个客户对应多个联系人,多个联系人对应一个客户,因此 客户 和 联系人 是一对多 关联关系。

2.有关SQL语句:只需在hibernate.cfg.xml配置文件中加上以下配置,然后当类获取Session时,即可让hibernate通过映射文件来自动生成数据表。

<!-- update表示检测实体类的映射配置和数据库的表结构是否一致 -->
<property name="hibernate.hbm2ddl.auto">update</property>

3.本示例的代码中有详细的注释,具体请参考注释内容。

4.学习多表映射配置要遵循的步骤:

    ①确定两张表之间的关系。

    ②在数据库中实现两张表之间的关系建立。

    ③在实体类中描述出两个实体之间的关系。

    ④在映射配置文件中建立两个实体和两张表之间的关系。

 

============================================================

============================================================

 

下面开始编写测试代码:

1.一对多关系映射配置及操作(客户和联系人两张表)

    ①确定两张表之间的关系:

        a.一个客户可以包含多个联系人。

        b.多个联系人可以属于同一个客户。

        c.客户和联系人之间的关系是一对多。

    ②在数据库中实现两张表之间的关系建立:

        a.实现一对多的关系,靠外键。

        b.客户表是主表,联系人表是从表。

        c.我们需要在联系人表中添加外键。

    ③在实体类中描述出两个实体之间的关系:

        a.主表的实体类应该包含从表实体类的集合引用。

        b.从表的实体类应该包含主表实体类的对象引用。

    ④在映射配置文件中建立两个实体和两张表之间的关系

============================

2.项目结构

超详细的Hibernate关联关系之双向的一对多关联关系的CRUD操作————学习至黑马程序员****

============================

首先是pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.lin</groupId>
  <artifactId>Hibernate_OneToMany_heima</artifactId>
  <version>0.0.1-SNAPSHOT</version>

<dependencies>
		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>3.6.10.Final</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>3.6.10.Final</version>
		</dependency>

		<!-- MySQL驱动包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.41</version>
		</dependency>
		
		<!-- slf4j -->
		<dependency>
		    <groupId>org.slf4j</groupId>
		    <artifactId>slf4j-nop</artifactId>
		    <version>1.7.25</version>
		    <scope>test</scope>
		</dependency>
		
		
		<!-- jstl、servlet-api、junit -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit-dep</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

</project>

============================

4.实体类和其对应的映射文件:

这里要注意的一点就是,如果要生成类的toString()方法,那么不要包含关联的实体类。

Customer.java

package com.lin.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
 * 客户的实体类
 * */
public class Customer implements Serializable {
	private static final long serialVersionUID = 1L;

	private Long custId;
	private String custName;
	private String custSource;
	private String sustIndustry;
	private String custLevel;
	private String custAddress;
	private String custPhone;
	
	//一对多关系映射:多的一方
	//主表实体应该包含从表实体的集合引用
	private Set<LinkMan> linkMans = new HashSet<LinkMan>(0);
	
	public Customer() {
		super();
	}
	public Long getCustId() {
		return custId;
	}
	public void setCustId(Long custId) {
		this.custId = custId;
	}
	public String getCustName() {
		return custName;
	}
	public void setCustName(String custName) {
		this.custName = custName;
	}
	public String getCustSource() {
		return custSource;
	}
	public void setCustSource(String custSource) {
		this.custSource = custSource;
	}
	public String getSustIndustry() {
		return sustIndustry;
	}
	public void setSustIndustry(String sustIndustry) {
		this.sustIndustry = sustIndustry;
	}
	public String getCustLevel() {
		return custLevel;
	}
	public void setCustLevel(String custLevel) {
		this.custLevel = custLevel;
	}
	public String getCustAddress() {
		return custAddress;
	}
	public void setCustAddress(String custAddress) {
		this.custAddress = custAddress;
	}
	public String getCustPhone() {
		return custPhone;
	}
	public void setCustPhone(String custPhone) {
		this.custPhone = custPhone;
	}
	public Set<LinkMan> getLinkMans() {
		return linkMans;
	}
	public void setLinkMans(Set<LinkMan> linkMans) {
		this.linkMans = linkMans;
	}
	
	@Override
	public String toString() {
		return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
				+ ", sustIndustry=" + sustIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
				+ ", custPhone=" + custPhone + "]";
	}
	
}

Customer.hbm.xml

<?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">

<hibernate-mapping package="com.lin.domain">
	
	<!-- name指定持久化类的类名,table指定数据表的表名 -->
	<class name="Customer" table="cst_customer">
		<id name="custId" column="cust_id">
			<generator class="native"/>
		</id>
		<property name="custName" column="cust_name"></property>
		<property name="custSource" column="cust_source"></property>
		<property name="sustIndustry" column="sust_industry"></property>
		<property name="custLevel" column="cust_level"></property>
		<property name="custAddress" column="cust_address"></property>
		<property name="custPhone" column="cust_phone"></property>
		<!-- 
			一对多关系映射:主表实体的映射配置
			       涉及的标签:
			    set:
					作用:用于配置set集合属性。
					属性: name:指定实体类中set集合的属性名称。
						table:指定从表的名称。在一对多配置时可不写。
						inverse:是否放弃维护关联关系的权利
							true:放弃
							false:不放弃(默认),如果不放弃,那么在双向一对多中保存数据的时候会有多余的update语句。
						cascade:配置级联操作。
							级联保存更新的取值:save-update
						lazy:配置是否使用延迟加载
							true:使用延迟加载(默认)
							false:不使用延迟加载
				key:
					作用:用于映射外键字段。
					属性:column:指定外键字段名称。
				one-to-many:
					作用:用于建立一对多的映射配置。
					属性:class:用于指定从表实体的名称。
		 -->
		 <set name="linkMans" table="cst_linkman" inverse="true" cascade="save-update" lazy="true">
		 	<key column="lkm_cust_id"></key>
		 	<one-to-many class="LinkMan"></one-to-many>
		 </set>
		
	</class>
	
</hibernate-mapping>

LinkMan.java

package com.lin.domain;

import java.io.Serializable;

/**
 * 联系人的实体类
 * */

public class LinkMan implements Serializable {
	private static final long serialVersionUID = 1L;

	private Long lkmId;
	private String lkmName;
	private String lkmGender;
	private String lkmPhone;
	private String lkmMobile;
	private String lkmEmail;
	private String lkmPosition;
	private String lkmMemo;
	
	//一对多关系映射,多的一方。
	//从表实体包含主表实体的对象引用
	private Customer customer;
	
	public Long getLkmId() {
		return lkmId;
	}
	
	public void setLkmId(Long lkmId) {
		this.lkmId = lkmId;
	}
	public String getLkmName() {
		return lkmName;
	}
	public void setLkmName(String lkmName) {
		this.lkmName = lkmName;
	}
	public String getLkmGender() {
		return lkmGender;
	}
	public void setLkmGender(String lkmGender) {
		this.lkmGender = lkmGender;
	}
	public String getLkmPhone() {
		return lkmPhone;
	}
	public void setLkmPhone(String lkmPhone) {
		this.lkmPhone = lkmPhone;
	}
	public String getLkmMobile() {
		return lkmMobile;
	}
	public void setLkmMobile(String lkmMobile) {
		this.lkmMobile = lkmMobile;
	}
	public String getLkmEmail() {
		return lkmEmail;
	}
	public void setLkmEmail(String lkmEmail) {
		this.lkmEmail = lkmEmail;
	}
	public String getLkmPosition() {
		return lkmPosition;
	}
	public void setLkmPosition(String lkmPosition) {
		this.lkmPosition = lkmPosition;
	}
	public String getLkmMemo() {
		return lkmMemo;
	}
	public void setLkmMemo(String lkmMemo) {
		this.lkmMemo = lkmMemo;
	}
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	@Override
	public String toString() {
		return "LinkMan [lkmId=" + lkmId + ", lkmName=" + lkmName + ", lkmGender=" + lkmGender + ", lkmPhone="
				+ lkmPhone + ", lkmMobile=" + lkmMobile + ", lkmEmail=" + lkmEmail + ", lkmPosition=" + lkmPosition
				+ ", lkmMemo=" + lkmMemo + "]";
	}
	
}

LinkMan.hbm.xml

<?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">

<hibernate-mapping package="com.lin.domain">
	
	<!-- name指定持久化类的类名,table指定数据表的表名 -->
	<class name="LinkMan" table="cst_linkman">
		<id name="lkmId" column="lkm_id">
			<generator class="native"/>
		</id>
		<property name="lkmName" column="lkm_name"></property>
		<property name="lkmGender" column="lkm_gender"></property>
		<property name="lkmPhone" column="lkm_phone"></property>
		<property name="lkmMobile" column="lkm_mobile"></property>
		<property name="lkmEmail" column="lkm_email"></property>
		<property name="lkmPosition" column="lkm_position"></property>
		<property name="lkmMemo" column="lkm_memo"></property>
		<!-- 
			一对多关系映射:从表实体的映射配置
			 	涉及的标签:many-to-one.
					作用:建立多对一的映射配置
					属性: name:从表实体中引用主表实体对象引用的名称
						class:指定属性所对应的实体类名称
						column:指定从表中外键字段的名称
						lazy:配置是否使用延迟加载
							false:使用立即加载
							proxy:是看load方法是延迟加载还是立即加载
							no-proxy:不使用,不用管。
		 -->
		<many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="save-update" lazy="proxy"></many-to-one>
		
	</class>
	
</hibernate-mapping>

============================

5.Hibernate的配置文件:

hibernate.cfg.xml

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

<!-- 
	Hibernate配置文件包含了连接持久层与映射文件所需的基本信息。
	(Hibernate配置文件主要用来配置数据库连接以及Hibernate运行时所需的各个属性的值。)

 -->
	
<hibernate-configuration>

	<session-factory>
		<!-- 数据库连接设置 -->
		<!-- 配置数据库JDBC驱动 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<!-- 配置数据库连接URL -->
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
		<!-- 配置数据库用户名 -->
		<property name="hibernate.connection.username">root</property>
		<!-- 配置数据库密码 -->
		<property name="hibernate.connection.password">000000</property>
		<!-- 配置JDBC内置连接池 -->
		<property name="connection.pool_size">1</property>
		<!-- 配置数据库方言 -->
		<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 配置Hibernate采用何种方式生成DDL语句 -->
		<!-- update表示检测实体类的映射配置和数据库的表结构是否一致 -->
		<property name="hibernate.hbm2ddl.auto">update</property>		
		<!-- 输出运行时生成的SQL语句 -->
		<property name="show_sql">true</property>
		
		<!-- 列出所有的映射文件 -->
		<mapping resource="hibernate/mappings/LinkMan.hbm.xml" />
		<mapping resource="hibernate/mappings/Customer.hbm.xml" />
	</session-factory>

</hibernate-configuration>

============================

6.Hibernate的工具类:

在这个类中添加了main方法,运行main方法后hibernate即可根据映射文件自动生成表。

HibernateUtil.java

package com.lin.utils;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

	private static SessionFactory sessionFactory;
	private static Configuration configuration;
	//创建线程局部变量threadLocal,用来保存Hibernate的Session
	private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
	
	//使用静态代码块初始化Hibernate
	static{
		try{
			//如果不指定hibernate的配置文件位置,那么它会默认到classpath路径下查找名为hibernate.cfg.xml的文件
			Configuration cfg = new Configuration().configure("/hibernate/hibernate.cfg.xml");
			//创建SessionFactory
			sessionFactory = cfg.buildSessionFactory();
		}catch(Throwable ex){
			throw new ExceptionInInitializerError(ex);
		}
	}
	
	//获得SessionFactory
	public static SessionFactory getSessionFactory(){
		return sessionFactory;
	}
	
	
	//获得ThreadLocal对象管理的Session实例
	public static Session getSession() throws HibernateException {
		Session session = (Session)threadLocal.get();
		if(session == null || session.isOpen()){
			if(sessionFactory == null){
				rebuildSessionFactory();
			}
			//通过SessionFactory对象创建Session对象
			session = (sessionFactory != null)?sessionFactory.openSession():null;
			//将新打开的Session实例保存到线程局部变量threadLocal中
			threadLocal.set(session);
		}
		
		return session;
	}
	
	//关闭Session实例
	public static void closeSession() throws HibernateException {
		//从线程局部变量threadLocal中获取之前存入的Session实例
		Session session = (Session)threadLocal.get();
		threadLocal.set(null);
		if(session != null){
			session.close();
		}
	}
	
	
	//重建SessionFactory
	public static void rebuildSessionFactory() {
		try{
			configuration.configure("/hibernate/hibernate.cfg.xml");
			sessionFactory = configuration.buildSessionFactory();
		}catch(Exception e){
			System.out.println("Error Creating SessionFactory ");
			e.printStackTrace();
		}
	}
	
	
	//关闭缓存和连接池
	public static void shutdown(){
		getSessionFactory().close();
	}
	
    //main方法
	public static void main(String[] args){
		HibernateUtil.getSession();
	}
}

============================

7.Hibernate一对多关联关系的CRUD测试:

package com.lin.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.lin.domain.Customer;
import com.lin.domain.LinkMan;
import com.lin.utils.HibernateUtil;

/**
 * 一对多关系的CRUD操作
 * */
public class HibernateOneToManyTest {

	/**
	 * 保存操作。
	 * 正常的保存:创建一个新的联系人(数据库中没有),需要关联一个客户(数据库中有)
	 * */
	@Test
	public void saveTest1(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		//1.查询一个客户
		Customer c1 = (Customer) session.get(Customer.class, 1L);
		//2.创建一个新的联系人
		LinkMan l = new LinkMan();
		l.setLkmName("联系人1");
		//3.建立客户和联系人的关联关系(让联系人知道属于哪个客户即可)
		l.setCustomer(c1);
		//4.保存联系人
		session.save(l);
		
		tx.commit();
		session.close();
	}
	
	/**
	 *   特殊的情况:
	 * 	   	创建一个客户(数据库中没有)和一个联系人(数据库中没有)。
	 *   	建立联系人和客户的双向关联关系。
	 *   	使用符合原则的保存。(原则是:先保存主表实体,再保存从表实体)。
	 *   
	 *   
	 *   此时保存会有问题,
	 *   	我们保存两个实体,应该只有两条insert语句,而执行结果却多了一条update语句。
	 *   解决办法:
	 *   	让客户在执行保存的时候,放弃维护关联关系的权利。
	 *   	配置的方式:
	 *   		在Customer的映射配置文件中的set标签上使用inverse属性。
	 *   		inverse的含义:是否放弃维护关联关系的权利
	 *   			true:放弃
	 *   			false:不放弃(默认)
	 * */
	@Test
	public void saveTest2(){
		
		//1.创建一个客户
		Customer c1 = new Customer(); //瞬时态
		c1.setCustName("客户2");
		//2.创建一个新的联系人
		LinkMan l = new LinkMan(); //瞬时态
		l.setLkmName("联系人2");
		//3.建立客户和联系人的关联关系(双向)
		l.setCustomer(c1);
		c1.getLinkMans().add(l);
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		//4.保存,要符合原则
		session.save(c1); //持久态,有一级缓存和快照
		session.save(l); //持久态,有一级缓存和快照
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 保存操作:级联保存
	 * 
	 * 使用级联保存,
	 * 1.也可以配置在many-to-one上。
	 * 2.配置的方式是找到Customer的映射配置文件中的Set标签,在上面加入cascade属性:
	 * 		cascade:配置级联操作。
	 * 		级联保存更新的取值:save-update
	 */
	@Test
	public void saveTest3(){
		
		//1.创建一个客户
		Customer c1 = new Customer(); //瞬时态
		c1.setCustName("客户3");
		//2.创建一个新的联系人
		LinkMan l = new LinkMan(); //瞬时态
		l.setLkmName("联系人3");
		//3.建立客户和联系人的关联关系(双向)
		l.setCustomer(c1);
		c1.getLinkMans().add(l);
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		//4.保存,要符合原则
		session.save(c1); //持久态,有一级缓存和快照
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 级联保存2
	 * */
	@Test
	public void saveTest4(){
		
		//1.创建一个客户
		Customer c1 = new Customer(); //瞬时态
		c1.setCustName("客户4");
		//2.创建一个新的联系人
		LinkMan l = new LinkMan(); //瞬时态
		l.setLkmName("联系人4");
		//3.建立客户和联系人的关联关系(双向)
		l.setCustomer(c1);
		c1.getLinkMans().add(l);
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		//4.保存,要符合原则
		session.save(l); //持久态,有一级缓存和快照
		
		tx.commit();
		session.close();
	}
	
	/**
	 * 更新操作
	 * 
	 * 要求:
	 * 		创建一个新的联系人,查询一个已有客户。
	 * 		建立新联系人和已有客户的双向关联关系
	 * 		更新客户
	 * */
	@Test
	public void updateTest1(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		//1.查询一个客户
		Customer c1 = (Customer) session.get(Customer.class, 1L);
		//2.创建一个新的联系人
		LinkMan l = new LinkMan();
		l.setLkmName("联系人5");
		//3.建立客户和联系人的关联关系(双向)
		l.setCustomer(c1);
		c1.getLinkMans().add(l);
		//4.更新客户
		session.update(c1);
		
		tx.commit();
		session.close();
	}
	
	
	/**
	 * 删除操作
	 * 		1.删除从表数据就是单表操作。
	 * 		2.删除主表数据:
	 * 			看有没有从表数据引用
	 * 				没有引用:就是单表操作,直接删。
	 * 				有引用:
	 * 					在删除时,hibernate会把从表中的外键字段置为null,然后再删除主表数据。(注意:主表中要不能放弃维护从表数据,即inverse="false" )
	 * 					如果外键字段有非空约束,则hibernate不能更新外键字段为null,会报错。
	 * 					此时,如果仍然想删除,就需要使用级联删除。可将cascade="save-update,delete",同时必须配置inverse="true"
	 *
	 * 级联删除的使用: 在实际开发中,要慎重!
	 * 
	 * */
	@Test
	public void deleteTest(){
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		//1.查询一个客户
		Customer c1 = (Customer) session.get(Customer.class, 3L);
		//2.删除id为1的客户
		session.delete(c1);
		tx.commit();
		session.close();
	}
	
	
	
	/****************************************************
	
	 * Hibernate 中的查询操作:OID查询,HQL查询,QBC查询,SQL查询,对象导航查询。
	 * 
	 * 
	 * 以下通过一对多的来演示对象导航查询。
	 * 		当两个实体之间有关联关系时(关联关系可以使一对一,一对多(多对一),多对多中的任意一种)。
	 * 		我们通过调用getXxx方法即可实现查询功能(功能是由hibernate提供的)
	 * 			例如:
	 * 				customer.getLinkMans()就可以得到当前客户下的所有联系人
	 * 				linkman.getCustomer()就可以得到当前联系人下的所属客户。
	 *
	 *
	 *三种lazy属性的情况:
	 *		class标签的lazy属性:它只能管load方法是否是延迟加载。
	 *		set标签的lazy属性: 它管查询关联的集合对象是否是延迟加载。
	 *		many-to-one的lazy属性:它管查询关联的主表实体是否是立即加载。
	 *
	 ***************************************************/
	
	/**
	 * 查询id为1的客户下所有的联系人
	 * 		一对多时,根据一的一方查询多的一方时,需要使用延迟加载。(默认配置就是使用延迟加载)
	 * 		(如果这里需要改成立即加载,那么找到Customer的映射文件中的set标签,添加lazy属性,即 lazy="false"即可)
	 * */
	@Test
	public void selectTest1(){
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Customer c = (Customer) session.get(Customer.class, 1L);
		System.out.println(c);
		System.out.println(c.getLinkMans());
		
		tx.commit();
		session.close();
		
		
	}
	
	/**
	 * 查询id为1的联系人所属的客户
	 * 		多对一时,根据多的一方查询一的一方时,不需要使用延迟加载,而是使用立即加载,这里需要配置一下。(找到LinkMan的配置文件的many-to-one标签添加laze属性,即lazy="false"即可)
	 *		需要找到联系人的映射配置文件:在many-to-one标签上使用lazy属性
	 *			取值有:
	 *				false:使用立即加载。
	 *				proxy:是看load方法是延迟加载还是立即加载。
	 *				no-proxy:不使用,不用管。
	 * */
	@Test
	public void selectTest2(){
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		LinkMan l = (LinkMan) session.get(LinkMan.class, 1L);
		System.out.println(l);
		System.out.println(l.getCustomer());
		
		tx.commit();
		session.close();
		
		
	}
	
	/**
	 * 关于load方法改为立即加载的方式。
	 * 		找到查询实体的映射配置文件,它的class标签上也有一个lazy属性。
	 * 			含义是:是否延迟加载
	 * 				true:延迟加载(默认值)
	 * 				flase:立即加载
	 * */
	@Test
	public void selectTest3(){
		
		Session session = HibernateUtil.getSession();
		Transaction tx = session.beginTransaction();
		
		Customer c = (Customer) session.load(Customer.class,1L);
		System.out.println(c);
		
		tx.commit();
		session.close();
		
		
	}
}

==========================

至此,一对多关联关系的全部代码都在上面。测试效果就免了~