`
86asm
  • 浏览: 200037 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

hibernate入门(五):多对一

阅读更多

 七 关联关系讨论

 

 

1多对一关系映射

一个部门有可以有多个员工,而一个员工只属于一个部门。从员工角度看,很多员工会隶属一个部门。 现以实例说明,实例概要:一个部门类,只有id和部门名称两个属性。有一个员工类,有id和员工名称及部门对象三个属性。操作步骤如下:

>>步骤一,建立Depatment.java及实体配置文件:

 

package com.asm.hibernate.domain;
public class Department {
	private int id ;
	private String 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;
	}	
}

同包下的实体配置文件:Depart.hbm.xml

<?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="com.asm.hibernate.domain">
	<class name="Department">
		<id name="id">
			<generator class="native" />
		</id>
		<property name="name"></property>
	</class>
</hibernate-mapping>

 

以上的操作,没的什么可多言的,和前面的配置是一样的形式。

>>步骤二,Employee.java内容如下及实体配置文件

 

 

package com.asm.hibernate.domain;
public class Employee {
	private int id;
	private String name;
	private Department depart;
	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 Department getDepart() {
		return depart;
	}
	public void setDepart(Department depart) {
		this.depart = depart;
	}
}

 同包下的实体配置文件:Employee.hbm.xml

 

<?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="com.asm.hibernate.domain">

	<class name="Employee">
		<id name="id">
			<generator class="native" />
		</id>
		<property name="name"></property>
		<many-to-one name="depart" column="depart_id" />
	</class>
</hibernate-mapping>

 

先来说这个类文件,它的一个重要属性就是Department对象,这就是它所关联的一个外键,这里我们只必须记住一点,每个实体类对应于一张表,如果一张表想关联另一张表,则只需要在这张表所对应的实体类中引入它想关联表的实体类对象。再进行简单的配置即可。再来看配置文件,这里主要看这个<many-to-one name="depart" column="depart_id"></many-to-one>元素,它的name属性仍然是实体类中的属性。column为对应表的外键。可以留意下数据库表中的相关表。

>>修改主配置文件,增加以下内容以便找到相应的实体配置文件。

<mapping resource="com/dep/emp/Employee.hbm.xml"/>  

<mapping resource="com/dep/emp/Depart.hbm.xml"/>

>>步骤四,编写测试类。类中省略导入包的内容。

package com.asm.hibernate.test;
public class ManyToOneTest {
	public static void main(String[] args) {
		add();
	}
	static void add() {
		Session s = null;
		Transaction tx = null;
		try {
			Department depart = new Department();
			depart.setName("departName");
			Employee emp = new Employee();
			emp.setName("empName");
			emp.setDepart(depart);

			s = HibernateUtil.getSession();
			tx = s.beginTransaction();

			s.save(depart);
			s.save(emp);
		// 交换以上两句的位置,看Hibernate执行的sql语句。会再增加一条更新操作。
			tx.commit();
		} finally {
			if (s != null)
				s.close();
		}
	}
}

 

说明:以前插入新的记录,都要传递一个实体对象,而这里没有这么做,原因是为了体现出一个插入记录的顺序问题,仔细观察add()方法,发现先保存的是Department对象,再保存的是Employee对象,原因是什么?这里略作说明,我们知道此项目设计的是让Employee表来关联Department表,而要想关联此表,必须保证此表已进行存储,这里暂时这样理解,也可以试试颠倒save方法的顺序,或是不保存depart来看看效果,这样也许有助理解。

简要说明,以上提到的尝试性操作:颠倒顺序,可以通过,只是增加了一条更新操作;不保存dep则不能通过,原因是此实体对象没有保存;再测试,如果注释掉“depart.setDname("deptName");”后面按正常顺序执行,发现是能正确执行的。只是在数据库的employee表中depart_id字段为null,如果我们在前面设置<many-to-one name="depart" column="depart_id">中增加:not-null="true"这个属性,再来执行将会报“不能为空的错误”。通过增加这个属性,可以让我们更好理解如何建立两个对象的关联。

>>步骤五,再探查询方法。接上面,在测试类中增加一个查询方法,内容如下:

static Employee query(int empId) {
		Session s = null;
		try {
			s = HibernateUtil.getSession();
			Employee emp = (Employee) s.get(Employee.class, empId);
			System.out.println("Department Name:" + emp.getDepart().getName());
			return emp;
		} finally {
			if (s != null)
				s.close();
		}
	}

  

随后再在主方法中增加如下内容:便可以测试结果:

query(1);

对结果的说明分析如果在以往的JDBC操作中,我们想得到这个部门的信息,需要查两次才能得到,这里的 Hibernate就实现了这一优化,如果我们开启了控制台的数据库显示功能(主配置文件中开启,前面已提到),便可以查看下数据库的执行操作,并切实感受到这里实际执行了两步查询操作,在以后的操作中,建议开启此属性,以便切实体会数据库操作。

>>步骤六,增加一个新的查询方法query2,内容如下,注意和query区别:

static Employee query2(int empId) {
		Session s = null;
		try {
			s = HibernateUtil.getSession();
			Employee emp = (Employee) s.get(Employee.class, empId);
			Hibernate.initialize(emp.getDepart()); 
			//上一句作用后面会作说明,这里略作了解
			return emp;
		} finally {
			if (s != null)
				s.close();
		}
	}

 

main方法中增加如下内容进行测试:

Employee emp = query2(1);

System.out.println(emp.getDepart().getName());

 

 

分享到:
评论
3 楼 86asm 2010-05-04  
回复cnyangqi:
第一个问题,我在第一节已经粗粗地提到过,<hibernate-mapping package="hibernate.entities">   package相当于一个包,它下面可以有很多class.
第二个问题,在后面章节会对级联有一个较详细的讲解。

自己研究出这两点,不错。



2 楼 cnyangqi 2010-05-03  
还有我这个注释了一个有趣的错误^^兄台有兴趣,一起研究下^^

package hibernate.test;

import hibernate.entities.Department;
import hibernate.entities.Employee;
import hibernate.util.HibernateUtil;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class ManyToOneTest {

	static void add() {
		Department depart = new Department();
		depart.setName("工程部");

		Employee emp = new Employee();
		emp.setName("jack");
		emp.setDepart(depart);

		Session s = HibernateUtil.getSession();
		Transaction ts = s.beginTransaction();

		try {
			s.save(emp);
			ts.commit();
		} finally {
			if (s != null) {
				s.close();
			}
		}
	}

	static Employee query(int empId) {
		Session s = HibernateUtil.getSession();

		try {
			//Employee emp = (Employee) s.get(Employee.class, empId);// 推断这里emp对象还将session 一并接受了
			//System.out.println(emp.getDepart().getName());
			//return emp;
			return (Employee) s.get(Employee.class, empId);
		} finally {
			if (s != null) {
				s.close();
			}
		}
	}

	static Employee query2(int empId) {
		Session s = HibernateUtil.getSession();

		try {
			Employee emp = (Employee) s.get(Employee.class, empId);
			Hibernate.initialize(emp.getDepart());
			return emp;
		} finally {
			if (s != null) {
				s.close();
			}
		}
	}

	public static void main(String[] args) {
		add();
		System.out.println("添加的员工姓名为:" + query(1).getName());
		//System.out.println("添加的员工部门为:" + query(1).getDepart());// 如果直接返回Employee的话, 报错 session 对象缺失
		System.out.println("H添加的员工部门为:" + query2(1).getDepart().getName());
	}
}

1 楼 cnyangqi 2010-05-03  
兄弟,在这篇文章这里给你补充完善一下^^

1,减少更新hibernat.cfg.xml主配置文件以及entity配置文件的方法:
将所有的entity类配置都写在一个配置文件里面,集体作为一个文件载入主配置文件即可
如下:
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory name="foo">

		<property name="hibernate.connection.provider_class">org.hibernate.connection.ProxoolConnectionProvider</property>
		<property name="hibernate.proxool.pool_alias">proxool</property>
		<property name="hibernate.proxool.xml">proxool.xml</property>

		<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
		<property name="hibernate.show_sql">true</property>

		<property name="hibernate.hbm2ddl.auto">create</property>
		<!--		<property name="hibernate.hbm2ddl.auto">update</property>-->

		<mapping resource="hibernate/entities/entities.hbm.xml" />

	</session-factory>
</hibernate-configuration>


entities.hbm.xml文件如下:
<?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="hibernate.entities">
		
	<class name="User" table="oauser">
	
				
		<id name="usID">
		
			            
			<generator class="native" />
		</id>
		
		
		<property name="usName"></property>
		<property name="usPwd"></property>
		<property name="usRole"></property>
	</class>
	
	<class name="Department" >
		<id name="id"><generator class="native" /></id>
		<property name="name"></property>
	</class>
	
	<class name="Employee" >
		<id name="id"><generator class="native" /></id>
		<property name="name"></property>
		<!--此处配置的depart_id没任何其他意义,仅为一个表里起的一个字段名而已!-->
		<many-to-one name="depart" column="depart_id" cascade="save-update"></many-to-one>
	</class>
	
</hibernate-mapping>


2,减少调用save方法,及出错概率^^
直接在配置中增加“cascade="save-update"”,关联保存,保存Employee对象的时候,自动保存Department对象。

以上是我研修到你这里时候的一些发现^^我比较懒惰的^^

相关推荐

Global site tag (gtag.js) - Google Analytics