Hibernate学习之级联操作2——一对多双向自身关联关系

上一篇记录了Hibernate的级联操作中的一对多关系,类似于教师和学生的一对多关系,这一篇记录的是Hibernate的级联操作中一对多双向自身关联关系,举例如下图:


在上图中,食物被分为蔬菜类和水果类,蔬菜类下又有西红柿,水果类下又有苹果和橘子,这几个不同的节点都可以用一个类来表示,这就是一对多双向自身关联关系,在代码中我们就把这些节点抽象为一个类Category,该类的代码如下所示:

package com.test.model;

import java.util.Set;

public class Category {

	private Integer id;
	private String name;
	private Category parentCategory;
	private Set<Category> childCategories;

	public Category(String name, Category parentCategory,
			Set<Category> childCategories) {
		super();
		this.name = name;
		this.parentCategory = parentCategory;
		this.childCategories = childCategories;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Category getParentCategory() {
		return parentCategory;
	}

	public void setParentCategory(Category parentCategory) {
		this.parentCategory = parentCategory;
	}

	public Set<Category> getChildCategories() {
		return childCategories;
	}

	public void setChildCategories(Set<Category> childCategories) {
		this.childCategories = childCategories;
	}

}
Category类中包含一个id和name,然后每个节点有0个或1个父节点,用成员变量parentCategory表示,该变量也是Category类型,若parentCategory为null,则代表跟节点,其次,每个节点可能有多个子节点,在类中就用一个集合表示,childCategories是一个Set集合,里面装的是Category类型的对象。

下面为Category类编写对应的hbm文件,Category.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">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Category" table="category">
        <id name="id" type="int">
            <column name="id" />
            <generator class="increment" />
        </id>
        <property name="name" type="string">
        	<column name="name" length="20"></column>
        </property>
        <set name="childCategories" cascade="all">
        	<key column="parent_id"></key>
        	<one-to-many class="com.test.model.Category"/>
        </set>
        <many-to-one name="parentCategory" class="com.test.model.Category" column="parent_id"></many-to-one>
    </class>
</hibernate-mapping>
可以看到,该hbm文件与上一篇中的hbm不同之处在于,它既有one-to-many标签,又有many-to-one标签,证明Category类是一对多双向自身关联的,Category类对应的数据库表如下:



接下来我们编写测试代码,测试hibernate对这种一对多双向自身关联的支持:

package com.test;

import java.util.HashSet;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.test.model.Category;

public class TestMain {
	private Category foodCategory;
	
	private void init(){
		foodCategory = new Category("食物", null, new HashSet<Category>());
		
		Category fruitCategory = new Category("水果", null, new HashSet<Category>());
		Category vegetableCategory = new Category("蔬菜", null, new HashSet<Category>());
		
		Category appleCategory = new Category("苹果", null, new HashSet<Category>());
		Category orangeCategory = new Category("橘子", null, new HashSet<Category>());
		Category tomatoCategory = new Category("西红柿", null, new HashSet<Category>());
		
		foodCategory.getChildCategories().add(fruitCategory);
		foodCategory.getChildCategories().add(vegetableCategory);
		fruitCategory.getChildCategories().add(appleCategory);
		fruitCategory.getChildCategories().add(orangeCategory);
		vegetableCategory.getChildCategories().add(tomatoCategory);
		
		fruitCategory.setParentCategory(foodCategory);
		vegetableCategory.setParentCategory(foodCategory);
		appleCategory.setParentCategory(fruitCategory);
		orangeCategory.setParentCategory(fruitCategory);
		tomatoCategory.setParentCategory(vegetableCategory);
	}
	
	private void test(){
		init();
		Session session = HibernateSessionFactory.getSession();
		Transaction trans = session.beginTransaction();
		try {
			session.save(foodCategory);
			trans.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			trans.rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}

	public static void main(String[] args) {
		new TestMain().test();
	}

}

执行上面的代码,在控制台可以看到如下输出:

Hibernate学习之级联操作2——一对多双向自身关联关系_第1张图片

在数据库中,可以看到增加了如下数据:

Hibernate学习之级联操作2——一对多双向自身关联关系_第2张图片

而我们在代码中,只保存了一个foodCategory对象,hibernate的级联操作自动为我们加入了其他的对象到数据库,执行删除时,我们将上面的代码中的一句:

session.save(foodCategory);
注释掉并添加:

session.delete(session.get(Category.class, 1));
可以看到控制台的输出如下:

Hibernate学习之级联操作2——一对多双向自身关联关系_第3张图片

数据库category表中的数据都被删除,这就是Category.hbm.xml文件中配置的cascade="all"这句起的作用

需要注意的是,如果Category中没有默认的构造方法,在执行上面的delete时会报错,因为如果没有默认的构造方法,hibernate框架就无法使用反射机制去创建对象


源码下载点击这里














你可能感兴趣的:(Hibernate,一对多,双向自身关联)