随笔-35  评论-97  文章-0  trackbacks-0

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 三告习习 阅读(1344) 评论(2)  编辑  收藏 所属分类: emf/gef/gmf

评论:
# re: [emf-query与emf-ocl] EMF-Query与EMF-OCL学习笔记系列六(Executing Queries) 2007-12-12 14:56 | JetGeng
强,学习了。  回复  更多评论
  
# re: [emf-query与emf-ocl] EMF-Query与EMF-OCL学习笔记系列六(Executing Queries) 2007-12-19 10:55 | drnstar
请问博主,emf-query和ocl-query之间有什么区别?  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: