首先我们来看下图:
每种商品类别代表一个Category对象,每一个Category可以和父列表关联,同时也可以和子类别关联,为了表达这种一对多的双向自身关联关系可以在Category类中定义两个属性:
parentCategory:引用父类别对象
childCategories:引用一组子类别对象
下面看看Category的源代码:
public class Category implements Serializable{
private Lang id;
private String name;
private Category parentCategory;
private Set childCategories;
....// get,set方法略,手写的
}
Category类的映射文件如下:
<set name="childCategories" cascade="save-update" inverse="true">
<key column="category_id" />
<one-to-many class="com.fyw.Category" />
</set>
下面我们来分析进行级联操作时的执行步骤:
(1)saveCategoryWidthCascade():当set属性的cascade为save-update时:
tx = session.beginTransaction();
Category foodCategory = new Category("food",null,new HashSet());
Category fruitCategory = new Category("fruit",null,new HashSet());
Category vegetableCategory = new Category("vegetable",null,new HashSet());
Category appleCategory = new Category("apple",null,new HashSet());
Category orangeCategory = new Category("orange",null,new HashSet());
Category tomatoCategory = new Category("tomato",null,new HashSet());
// 建立食品和水果之间的关系
foodCategory.getChildCategories().add(fruitCategory);
fruitCategory.setParentCategory(foodCategory);
// 建立食品和蔬菜之间的关系
foodCategory.getChildCategories().add(vegetableCategory);
vegetableCategory.setParentCategory(foodCategory);
// 建立水果和苹果之间的关系
fruitCategory.getChildCategories().add(appleCategory);
appleCategory.setParentCategory(fruitCategory);
// 建立水果和桔子之间的关系
fruitCategory.getChildCategories().add(orangeCategory);
orangeCategory.setParentCategory(fruitCategory);
// 建立西红柿和水果之间关系
fruitCategory.getChildCategories().add(tomatoCategory);
tomatoCategory.setParentCategory(fruitCategory);
session.save(foodCategory);
tx.commit();
当set的cascade为save-update时,Hibernate在持久化Category对象时会自动持久化关联的其他Category对象。
(2)modifyCategoryAssociation():该方法演示如何修改关联对象之间的关系。代码如下:
tx = session.beginTransaction();
Category tomatoCategory = findCategoryByName(session,"tomato");
Category fruitCategory = findCategoryByName(session,"fruit");
Category vegetableCategory = findCategoryByName(session,"vegetable");
// 建立西红柿和蔬菜之间关系
vegetableCategory.getChildCategories().add(tomatoCategory);
tomatoCategory.setParentCategory(vegetableCategory);
// 删除西红柿和水果之间关系
fruitCategory.getChildCategories().remove(tomatoCategory);
tx.commit();
首先通过findCategoryByName方法分别加载tomatoCategory,fruitCategory和vegetableCatgory对象并返回符合要求的:
public Category findCategoryByName(Session session,String name)throws Exception{
List results = session.find("from Category as c where c.name =‘"+name+"‘");
return (Category)results.iterator().next();
}
findCategoryByName方法和modifyCategoryAssociation方法共用一个session实例,通过findCategoryByName返回的Category仍处于持久化状态。
modifyCategoryAssociation方法会更新这三个对象之间的关联关系,当Hibernate在清理缓存中已持久化的对象时,会自动按照他们的状态改变来同步更新数据库。
虽然缓存中tomcatoCategory,fruitCategory,vegetableCategory这三个对象都发生了变化,但是set的inverse属性设置为true,Hibernate只执行一条sql语句。