EMF-Query 的查询语句结构也是很简单的
SELECT
FROM [source]
WHERE [condition]
很像我们平常的SQL语句吧,但是不同的是SELECT、FROM 和WHERE 都是由对象来组合的。
查询的策略是:将所需要检索的对象源(EObject Source)转换成一棵对象树,通过遍历这棵对象树,依次将树中的对象与所需要检索的条件进行匹配,选择匹配成功的。在这个过程中,对象数会依据一定的算法来对对象树进行裁减,目的是减少不必要的枝遍历,提高查询效率。EMF Query在构造Condition的时候,提供了PruneHandler接口,用于判断当前的eObject对象是否需要进行裁减遍历行为。
看看类的结构吧:
SELECT是通过与WHERE和FROM关联(WHERE和FROM为SELECT的两个属性)来完成查询语句的构造的,而WHERE又通过与EObjectCondition关联来完成条件的注入。注意这里是EObjectCondition,如果你的条件值类型的,可以通过条件适配器来转换,前面帖子有介绍。对于查询是否发生例外,你可以通过查询的结果IQueryResult来的getException获取例外,如果获取内容为null,说明没有例外发生。
查询的对象源可以是单个的EObject,也可以是EObject的集合,还可以是IEObjectSource。
看看具体的例子来体会一下究竟如何使用SELECT查询。 模型还是前面用到的模型。
数据有下面来确定:
ShopFactory shopFactory = ShopFactory.eINSTANCE;
// 商品种类
Category food = shopFactory.createCategory();
food.setName("食物");
Category commodity = shopFactory.createCategory();
commodity.setName("日用品");
// 食品类产品
Product creamery = shopFactory.createProduct();
creamery.setName("牛奶");
Product apple = shopFactory.createProduct();
apple.setName("苹果");
Product pork = shopFactory.createProduct();
pork.setName("猪肉");
food.getProducts().add(creamery);
food.getProducts().add(apple);
food.getProducts().add(pork);
creamery.setCategory(food);
apple.setCategory(food);
pork.setCategory(food);
// 日用品类产品
Product towel = shopFactory.createProduct();
towel.setName("毛巾");
commodity.getProducts().add(towel);
towel.setCategory(commodity);
Shop shop = shopFactory.createShop();
shop.setName("人人乐");
shop.getCategories().add(food);
shop.getCategories().add(commodity);
假定查询需求:查“人人乐”中种类为“食品”的所有产品(方法有多种,下面给出其中一种)
//假定查询需求:查“人人乐”中种类为“食品”的所有产品(方法有多种,下面给出其中一种)
//1、从名称入手,首先,确定种类的名称
Condition nameForFoodCategory = new SubStringValue("食物");
//2、名称是什么呢?种类的属性,所以用“属性值条件” EObjectAttributeValueCondition
EObjectCondition foodCategory = new EObjectAttributeValueCondition(
ShopPackage.Literals.NAMED_ELEMENT__NAME,nameForFoodCategory);
//3、但是,你的入口地方是“人人乐”商店shop哦,商品与产品种类是什么关系?关联! 那就用“关联条件” EObjectReferenceValueCondition 吧
EObjectCondition foodProducts = new EObjectReferenceValueCondition(ShopPackage.eINSTANCE.getProduct_Category(),foodCategory);
//最后、执行语句:从“人人乐”商店里按条件(种类名称为“食物”的产品)查询
SELECT statement = new SELECT(new FROM(shop), new WHERE(foodProducts));
Collection results = statement.execute();
for(Object object : results)
{
System.out.println(object);
}
假定查询需求:查“人人乐”产品名为“毛巾”的产品品种类
//假定查询需求:查“人人乐”产品名为“毛巾”的产品品种类
Condition nameForProductTowel = new SubStringValue("毛巾");
EObjectCondition towelProduct = new EObjectAttributeValueCondition(
ShopPackage.Literals.NAMED_ELEMENT__NAME,nameForProductTowel);
EObjectCondition categoryForTowerl = new EObjectReferenceValueCondition(ShopPackage.eINSTANCE.getCategory_Products(),towelProduct,ConditionPolicy.ANY,EStructuralFeatureValueGetter.getInstance());
statement = new SELECT(new FROM(shop), new WHERE(categoryForTowerl));
results = statement.execute();
for(Object object : results)
{
System.out.println(object);
}
假定查询需求:查“人人乐”产品种类中少于3的产品种类
在这里,我用继承EObjectCondition的子类来构造条件:
private static class ProductsLessThan3Condition extends EObjectCondition {
public ProductsLessThan3Condition() {
super(PruneHandler.NEVER);
}
@Override
public boolean isSatisfied(EObject eObject) {
if (eObject instanceof Category) {
Category category = (Category) eObject;
EList products = category.getProducts();
if (products.size() < 3)
return true;
}
return false;
}
}
然后像平常一样的查询就可以了:
//假定查询需求:查“人人乐”产品种类中少于3的产品种类
statement = new SELECT(new FROM(shop), new WHERE(new ProductsLessThan3Condition()));
results = statement.execute();
for(Object object : results)
{
System.out.println(object);
}
接着看看UPDATE:
UPDATE是SELECT的一个子类,它是通过关联SET来达到更新数据的目的。数据更新是在查询的基础上实施的。
假定更新数据需求:将产品数小于3的产品种类改名为“被修改后的种类名称”。
//将产品数小于3的产品种类改名为“被修改后的种类名称”
IQueryResult updateResult = new UPDATE(new FROM(shop),new WHERE(new ProductsLessThan3Condition()),new SET(){
@Override
public boolean set(EObject eObject)
{
if(eObject instanceof Category)
{
Category category = (Category)eObject;
category.setName("被修改后的种类名称");
return true;
}
return false;
}}).execute();
if(updateResult.getException() != null){
System.out.println(updateResult.getException().getMessage());
}else{
for(Iterator it = updateResult.iterator(); it.hasNext();)
{
Object object = (Object)it.next();
System.out.println(object);//看看是不是将名称改了
}
}
在查询的过程进行对树的裁剪留到下一节。EMF-Query查询可以结合Hibernate和JDO来进行持久化,这些也留在后面吧。
很快经入OCL了,兴奋ing~~~~~~~~~
posted on 2007-06-12 22:42
三告习习 阅读(1364)
评论(2) 编辑 收藏 所属分类:
emf/gef/gmf