hibernate的运用表之间的级联关系

hibernate的应用表之间的级联关系
1.联合主键映射
<?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="tarena.domain">
	<class name="Person" table="person">
<!--联合主键的配置-->
		<composite-id name="key" class="PersonKey">
			<key-property name="first" type="string">
				<column name="first"></column>
			</key-property>
			<key-property name="last" type="string">
				<column name="last"></column>
			</key-property>
		</composite-id>
		<property name="sex" type="string">
			<column name="sex"></column>
		</property>
	</class>
</hibernate-mapping>

pojo类实现,要有equals()和hashCode()方法
package tarena.domain;

public class Person {
	private PersonKey key;
	private String sex;
	public PersonKey getKey() {
		return key;
	}
	public void setKey(PersonKey key) {
		this.key = key;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + ((key == null) ? 0 : key.hashCode());
		result = PRIME * result + ((sex == null) ? 0 : sex.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Person other = (Person) obj;
		if (key == null) {
			if (other.key != null)
				return false;
		} else if (!key.equals(other.key))
			return false;
		if (sex == null) {
			if (other.sex != null)
				return false;
		} else if (!sex.equals(other.sex))
			return false;
		return true;
	}
}

PsersonKey类
package tarena.domain;

public class PersonKey implements java.io.Serializable{
	private String first;
	private String last;
	public PersonKey(){}
	public PersonKey(String first, String last) {
		super();
		this.first = first;
		this.last = last;
	}
	public String getFirst() {
		return first;
	}
	public void setFirst(String first) {
		this.first = first;
	}
	public String getLast() {
		return last;
	}
	public void setLast(String last) {
		this.last = last;
	}
}


2.外键,多对一/一对多
<!--Dept.hbm.xml-->
<hibernate-mapping package="tarena.domain">
	<class name="Dept" table="dept" lazy="true">
		<id name="id" type="integer">
			<column name="id"></column>
<!--id标识的生成策略,依赖于底层数据库的支持-->
			<generator class="native"></generator>
		</id>
		<property name="dname" type="string">
			<column name="dname"></column>
		</property>
<!--cascade="all"表示表示对象表之间的级联关系;one-to-many中级联的对象应由多(many)的一方来提供支持,many-to-many中可以是任意方-->
		<set name="emps" cascade="all" inverse="true">
			<key column="dept_id"></key>
			<one-to-many class="Emp"/>
		</set>
	</class>

<!--Emp.hbm.xml-->
<class name="Emp" table="emp">
		<id name="id" type="integer">
			<column name="id"></column>
			<generator class="native"></generator>
		</id>
		<property name="ename" type="string">
			<column name="ename"></column>
		</property>
<!--class对应的级联表对象,fetch="join"表示表与表之间的抓取策略-->
		<many-to-one name="dept" column="dept_id" class="Dept" fetch="join">
		</many-to-one>
	</class>
</hibernate-mapping>

测试类,具体实现在后面依次添加
public class DeptDAOTest {

DeptDAO deptDao;

	@Before
	public void init(){
		deptDao = new DeptDAO();
	}
//	@Test
	public void testAdd1(){
		Dept dept = new Dept();
		dept.setDname("testing");
		deptDao.add(dept);
	}
//	@Test
	//测试级联添加
	public void testAdd2(){
		Dept dept = new Dept();
		dept.setDname("design");
		//添加新员工designer1
		Set<Emp> emps = new HashSet<Emp>();
		Emp emp1 = new Emp();
		emp1.setEname("designer1");
		emp1.setDept(dept);
		emps.add(emp1);
		//	添加新员工designer2
		Emp emp2 = new Emp();
		emp2.setEname("designer2");
		emp2.setDept(dept);
		emps.add(emp2);

		//将员工集合emps指定给dept对象
		dept.setEmps(emps);
		deptDao.add(dept);
	}
	@Test
	//测试级联删除
	public void testDelete(){
		Dept dept = deptDao.findById(4);
		deptDao.delete(dept);
	}
//	@Test
	public void testFindById(){
		Dept dept = deptDao.findById(1);
		System.out.println(dept.getId()+":"+dept.getDname());
		Set<Emp> emps = dept.getEmps();
		for(Emp emp:emps){
			System.out.println(emp.getId()+":"+emp.getEname());
		}
		System.out.println("一共有"+emps.size()+"个员工");
	}
}

DeptDao代码
package tarena.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;
import tarena.domain.Dept;
import tarena.util.HibernateUtil;

public class DeptDAO {
	public Dept findById(int id){
		Session session = HibernateUtil.getSession();
		Dept dept = (Dept)session.load(Dept.class, id);
		return dept;
	}
	public void add(Dept dept){
		Session session = HibernateUtil.getSession();
		Transaction txt = session.beginTransaction();
		session.save(dept);
		txt.commit();
		HibernateUtil.closeSession();
	}
	public void delete(Dept dept){
		Session session = HibernateUtil.getSession();
		Transaction txt = session.beginTransaction();
		session.delete(dept);
		txt.commit();
		HibernateUtil.closeSession();
	}
}


3.理解延迟加载,区分load和get方法
//load方法启用延迟加载,返回的对象是一个代理对象
//Dept dept = (Dept)session.load(Dept.class, 1);
//get方法不启用延迟加载,立刻检索数据表,返回对象实例
	Dept dept = (Dept)session.get(Dept.class, 1);
//HibernateUtil.closeSession();
//	如使用延迟加载,不要将session关闭,否则会影响后续取值操作
//可以在业务操作都完成后,再将session关闭。
//比如JavaWeb程序可以使用Filter控制session关闭
//hibernate的默认配置是启用延迟,所以在使用get方法时,
//可以Hibernate.initialize(obj),来对对象进行初始化加载,不过要在session.colse()之前
//或者可以把该对象的pojo类的映射文件的lazy="false",就可以了。


首先,配置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">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>
	<session-factory>
		<property name="myeclipse.connection.profile">mysql</property>
		<property name="connection.username">root</property>
		<property name="connection.password">1234</property>
		<property name="connection.url">
			jdbc:mysql://localhost:3306/hibernate
		</property>
<!-- 是否使用数据库本地话方言   -->
		<property name="dialect">
			org.hibernate.dialect.MySQLDialect
		</property>
		<property name="connection.driver_class">
			com.mysql.jdbc.Driver
		</property>
<!-- 是否打印hql语句   -->
		<property name="show_sql">true</property>
<!-- 对象的关系映射   -->
		<mapping resource="tarena/mapping/Person.hbm.xml" />
		<mapping resource="tarena/mapping/Dept.hbm.xml" />
		<mapping resource="tarena/mapping/Emp.hbm.xml" />
	</session-factory>
</hibernate-configuration>

hibernateUtil的配置
package tarena.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

	public static Configuration conf;
	public static SessionFactory sf;
	public static ThreadLocal<Session> sessionLocal = new ThreadLocal<Session>();

	static{
		conf = new Configuration();
		conf.configure();//默认加载src下面的hibernate.cfg.xml配置文件
		sf = conf.buildSessionFactory();
	}

	public static Session getSession() {
		Session session = sessionLocal.get();
		if(session == null){
			session = sf.openSession();
			sessionLocal.set(session);
		}
		return session;
	}

	public static void closeSession(){
		Session session = sessionLocal.get();
		sessionLocal.set(null);
		if(session != null){
			session.close();
		}
	}
}

pojo类Dept
package tarena.domain;
import java.io.Serializable;
import java.util.Set;

public class Dept implements Serializable{
	private int id;
	private String dname;
	private Set<Emp> emps;

	public String getDname() {
		return dname;
	}
	public void setDname(String dname) {
		this.dname = dname;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public Set<Emp> getEmps() {
		return emps;
	}
	public void setEmps(Set<Emp> emps) {
		this.emps = emps;
	}
}