精通Hibernate——映射一对多双向自身关联关系

来源:互联网 发布:爱思for mac官方下载 编辑:程序博客网 时间:2024/05/22 10:28

首先我们来看下图:
这里写图片描述
每种商品类别代表一个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语句。

0 0
原创粉丝点击