当我们加载一个类时session会加载所有和该类直接关联或者间接关联的对象。
在对象关系映射文件中,用于映射持久化类之间关联关系的元素,如、和元素,都有一个cascade属性,他用于指定如何操纵与当前关联的对象,他的可选属性如下:
none:在保存、更新或删除对象时,忽略其他关联的对象,他是cascade默认属性
save-update:当通过session的save、update以及saveOrUpdate方法来保存或更新当前对象时,级联保存所有关联的新建的临时对象,并且级联更新所有关联的游离对象
delete:当通过session的delete方法删除当前对象时,级联删除所有关联的对象
all:包含save-update以及delete行为以外,对当前对象执行evict或lock操作时,也会对所关联的持久化对象执行evict或lock操作
delete-orphan:删除所有和当前对象解除关联关系的对象
all-delete-orphan:包含all和delete-orphan行为
我们以下面类的关系为例:
1、级联保存临时对象
saveFoodCategory()方法先创建三个Category临时对象,建立他们之间的关联关系,然后调用saveOrUpdate方法保存foodCategory对象。
public void saveFoodCategory() throws Exception{
Category foodCategory = new Category("food",null,new Hashset());
Category fruitCategory = new Category("fruit",null,new Hashset());
Category appleCategory = new Category("apple",null,new Hashset());
// 建立食品类别和水果类别之间的关系
foodCategory.addChildCategory(fruitCategory);
// 建立水果类别和苹果类别之间的关系
fruitCategory.addChildCategory(appleCategory);
saveOrUpdate(foodCategory);
}
saveOrUpdate方法调用session的saveOrUpdate方法来保存foodCategory对象。执行步骤如下:
1.由于foodCatogory为临时对象,因此session调用save方法来保存foodCategory对象
2.session通过foodCategory.getChildCategories方法导航到fruitCategory临时对象,调用save方法来保存fruitCategroy临时对象
3.session通过fruitCategory.getChildCategories方法导航到appleCategory临对象,调用save方法来保存appleCategory临时对象
Session在清理缓存的时候执行三条insert语句
insert into categories (name,category_id,id) values("food",null,1);
insert into categories (name,category_id,id) values("fruit",1,2);
insert into categories (name,category_id,id) values("food",2,3);
2、更新持久化对象
saveOrangeCategory()方法用于持久化一个orangeCategory对象,他会先调用findCategoryByName(session,”fruit”)方法,由于该查询方法与saveOrangeCategory()方法公用一个session,因此,他返回的fruitCategory对象处于持久化状态。接下来创建一个orangeCategory临时对象,建立fruitCategory与orangeCategory之间的关联关系。
3、持久化临时对象
saveVegetableCategory()方法用于持久化一个vegetableCategory临时对象
saveVegetableCategory()方法先调用findCategoryByName(“food”)方法,该方法不与saveVegetableCategory()方法公用一个session,因此返回的foodCategory对象处于游离状态。接下来创建一个vegetableCategory临时对象,建立foodCategory与vegetableCategory之间的关联关系。最后调用saveOrUpdate()保存vegetableCategory对象:
public void saveVegetableCategory() throws Exception{
// 返回的foodCategory是游离对象
Category foodCategory = findCategoryByName("food");
Category vegetableCategory = new Category("vegetable",null,new HashSet());
// foodCategory游离对象与vegetableCategory临时对象关联
foodCategory.addChildCategory(vegetableCategory);
saveOrUpdate(vegetableCategory);
}
saveOrUpdate方法调用Session的saveOrUpdate来保存vegetableCategory对象,Session的saveOrUpdate执行以下步骤:
1.由于vegetableCategory为临时对象,因此Session调用save方法持久化vegetableCategory对象。
2.Session通过vegetableCategory.getParentCategory()方法导航到foodCategory对象,由于foodCategory对象为游离对象,因此调用update方法更新foodCategory对象。
3.Session通过foodCategory.getChildCategories方法导航到fruitCategory对象,由于fruitCategory对象为游离对象,因此调用update方法更新fruitCategory对象
4、更新游离对象
updateVegetableCategory方法用于更新vegetableCategory对象的name属性,并且创建一个tomatoCategory对象,他与vegetableCategory对象关联
updateVegetableCategory方法先调用findCategoryByName(“vegetable”)方法,该查询方法不与updateVegetableCategory方法公用一个Session,因此返回的vegetableCategory对象处于游离状态。接下来修改vegetableCategory对象的name属性,然后创建一个tomatoCategory临时对象,建立vegetableCategory与tomatoCategory之间的关联关系,最后调用saveOrUpdate方法封信vegetableCategory对象
public void updateVegetableCategory() throws Exception{
//返回的vegetableCategory是游离对象
Category vegetableCategory = findCategoryByName("vegetable");
vegetableCategory.setName("green vegetable");
Category tomatoCategory = new Category("tomato",null,new HashSet());
//vegetableCategory游离对象与tomato临时对象关联
vegetableCategory.addChildCategory(tomatoCategory);
saveOrUpdate(vegetableCategory);
}
5、遍历对象图
navigateCategories方法先调用findCategoryByName(“fruit”)方法,由于该查询方法不与navegateCategories公用一个Session,因此他返回的fruitCategory对象处于游离状态。接下来调用navigateCategories(fruitCategory,categories)取得所有关联的Category游离对象
public void navigateCategores() throws Exception{
Category fruitCategory = findCategoryByName("fruit");
HashSet categories = new HashSet();
navigateCategories(fruitCategory,categories);
//打印categories集合中所有的Category对象
for(Iterator it = categories.iterator();it.hasNext();){
System.out.println(((Category)it.next()).getName());
}
}
navigateCategories方法利用递归算法,遍历所有与fruitCategory关联的父类别及类别Category对象,把他们存放在一个Set集合中:
private void navigateCategories(Category category,Set categories){
if(categories.contains(category) || category == null) return;
categories.add(category);
//递归遍历父类Category
navigateCategories(category.getParentCategory(),categories);
Set childCategories = category.getChildCategores();
if(childCategories == null) return;
//递归遍历所有子类Category
for(Iterator it = childCategores.interator();it.hasNext();){
navigateCategories((Category)it.next(),categories);
}
}