数据库Schema: (Oracle)
create table test_categories(
ID number(15) not null,
name varchar2(15),
category_id number(15),
primary key (id)
);
alter table categories add index idx_category_id
(category_id), add constraint
fk_category_id foreign key (category_id) references
categories(id);
public class Category { private Long id; private String name; private Category parentCategory; private Set<Category> childCategories; public Category() { // TODO Auto-generated constructor stub } public Category(String name, Category parentCategory, Set<Category> childCategories) { this.name = name; this.parentCategory = parentCategory; this.childCategories = childCategories; } }
这里Category类实现了自身的一对多, 每一个Category有一个父表和若干的字表。
父表是它上一层的类, 比如CPU的父类表是电脑硬件,
而CPU的子类表可以是intel cpu和 amd cpu. ( 双向就是指向父类和向子类)
表的结构关联如下:
=========================具体实例====================
这里我们用一个计算机硬件的分类来演示这个自身双向一对多。
结构图:
Category.hbm.xml代码:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.lj.zhang.category"> <class name="Category" table="test_category" lazy="false"> <id name="id" column="id" type="long"> <generator class="sequence"> <param name="sequence">cate_seq</param> </generator> </id> <property name="name" column="name" type="string"/> <set name="childCategories" cascade="all" inverse="true"> <key column="category_id"></key> <one-to-many class="com.lj.zhang.category.Category"/> </set> <many-to-one name="parentCategory" class="com.lj.zhang.category.Category" column="category_id"></many-to-one> </class> </hibernate-mapping>
hibernate代码:
Session session = HibernateUtil.openSession(); Transaction tx = null; tx = session.beginTransaction(); Category c=new Category("computer",null,new HashSet<Category>()); //这里没有通过cpu.setParent来指定父类, 而是直接在构造函数里将父类实例传递进去,下面都是这样。 //setParent也可以实现同样效果。 Category cpu=new Category("cpu",c,new HashSet<Category>()); Category motherboard=new Category("motherboard",c,new HashSet<Category>()); c.setChildCategories(ArraysHelper.asSet(cpu,motherboard)); Category intel_cpu=new Category("intel_cpu",cpu,new HashSet<Category>()); Category amd_cpu=new Category("amd_cpu",cpu,new HashSet<Category>()); cpu.setChildCategories(ArraysHelper.asSet(intel_cpu,amd_cpu)); Category asus=new Category("asus",motherboard,new HashSet<Category>()); Category giga=new Category("giga",motherboard,new HashSet<Category>()); motherboard.setChildCategories(ArraysHelper.asSet(asus,giga)); session.save(c); tx.commit(); session.close();
注意这里是通过oracle的sequence来给id赋值:
<id name="id" column="id" type="long"> <generator class="sequence"> <param name="sequence">cate_seq</param> </generator> </id>
通过该程序可以看到, 只要把这些类的实例通过java的方式赋值,最后save它们的最高级的父类对象, 所有的对象都会被存储到数据库中, 并建立对应关系。
个人感觉Hibernate对于Java程序员的便利性在这个例子中得到充分体现。
------------------------------
数据库里显示最高级父类的cate id是没有任何数值的, 我们可以设置oracle给这种情况一个-1.
不过这里再次执行发现还是什么都没有。因为要在hibernate那里设置一下。
找到category.hbm.xml