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
三告習習 閱讀(1376)
評論(2) 編輯 收藏 所屬分類:
emf/gef/gmf