這一節中我們繼續學習esper的事件部分内容。
對應官方的文檔為2.4-2.5
有些情況,一個事件的某個屬性本身又是一個事件。esper對這種稱作為fragment(碎片)和碎片類型。一個示例就是,兩個或者更多的事件可以組成和一個新的事件作為輸出,而這個輸出事件在将來可能又作為其他事件的一個碎片屬性。
碎片及類型屬性使得你可以組合事件,而無需使用java 反射api,這減少了事件底層操作處理。相關api見15.6,“event and event type”
pojo是指類對象通過像javabean風格的方法提供getter方法向外界開放内部屬性。這種事件類,也不是完全需要嚴格遵循javabean的約定,但一定要提供getter方法,或者是通過某種配置達到目的。
esper支援javabean風格的事件類,它可以是某個基類的擴充,或者是一個或者多個接口的實作。esper的時間模式和epl語句也支援指向java接口類和抽象類。
代表事件的類應該是不可變的。因為事件代表的是過去發生的動作或者狀态的改變,是以應該是不能改變的。但這也不是嚴格要求,esper引擎也接受可變的事件。
事件類的hashcode和equals方法無需實作。其實作也不會影響esper引擎的工作表現。
前面我們提到,我們支援遵循标準javabean約定的屬性類型,斌企鵝有一些是esper特定支援的:
1) simple 簡單屬性僅僅包含一個單一的可檢索的值。屬性的底層實作可能是java語言的内置類型(例如int,簡單對象java.lang.string)或更為複雜的對象,它可能是由java語言定義的、或者是應用定義的,或是第三方庫定義的。
2) indexed 索引屬性存儲的是同一類型的有序對象容器,容器内的對象可以通過索引單獨通路。
3) mapped javabean api的擴充,esper考慮任何由以string類型作為key的映射屬性。
4) nested 嵌套屬性是指該屬性所在的對象是一個事件的一個屬性。即它是事件屬性的屬性。
假如這裡有個newemployeeevent事件類。這裡的索引和映射屬性傳回的是java對象,但也可以傳回java的内置類型(例如int和string)。address對象和employee對象都可以嵌套它們自己的屬性,例如address裡面可以有街道名稱,employee中可以有雇員姓名。
public classnewemployeeevent {
public stringgetfirstname();
public addressgetaddress(string type);
public employeegetsubordinate(int index);
public employee[]getallsubordinates();
}
簡單事件屬性需要一個getter方法,用于傳回屬性值。在這個例子中,getfirstname方法傳回firstname事件屬性,它為string類型。
索引事件屬性需要如下的兩種getter方法的至少一種。第一種,以整形為參數傳回一個屬性值,例如getsuborinate方法;另一種方法是傳回整個數組對象,例如getallsubordinates方法。在epl或者事件模式語句中,索引屬性通過property[index]來通路。
映射事件屬性需要一個getter方法,它以string類型的關鍵字作為參數,傳回屬性值,例如getaddress方法。在epl或者事件模式語句中,映射屬性通過property(‘key’)來通路。
嵌套事件屬性需要一個getter方法用于傳回嵌套對象。getaddress和getsubordinate是映射和索引屬性,它們傳回的是一個嵌套對象。在epl和事件模式語句中,嵌套屬性通過property.nestedproperty來通路。
上述的這些屬性可以任意的進行複合。例如下面就是這些屬性的一些複合示例:
everynewemployeeevent(firstname='myname')
everynewemployeeevent(address('home').streetname='park avenue')
everynewemployeeevent(subordinate[0].name='anothername')
everynewemployeeevent(allsubordinates[1].name='thatname')
everynewemployeeevent(subordinate[0].address('home').streetname='water street')
類似的,這些文法可以應用在epl語句任何事件屬性名可以出現的地方,例如select清單,where語句,jion語句等。
select firstname,address('work'), subordinate[0].name, subordinate[1].name
from newemployeeevent
whereaddress('work').streetname = 'park ave'
屬性名遵循java标準:java.beans.introspector類和getbeaninfo方法傳回屬性名。此外,esper還可以通過配置一個辨別來關閉大小寫敏感,表2.4是屬性名和相應getter方法的示例。
方法 屬性名 示例
getprice()
price select pricefrom myevent
getname()
name select name frommyevent
getitemdesc()
itemdesc
select itemdesc frommyevent
getq() q select qfrom myevent
getqn() qn select qnfrom myevent
gets() s select sfrom myevent
2.5.3 參數化類型
當你的getter方法的到的是一個參數化的類型,例如索引屬性,iterable<myeventdata>,映射屬性map<string,myeventdata>,那麼這個參數化類型就是指向屬性的屬性表達式,它可以獲得屬性值。
public stringgetname();
public iterable<educationhistory>geteducation();
publicmap<string, address> getaddresses();
一個獲得屬性的表達式如下:
select name,education, education[0].date, addresses('home').street
epl語句可以更新事件的索引和映射屬性,提供了設定屬性的setter方法。
索引屬性的setter方法必須形如setpropertyname,并且有兩個參數,整形的索引參數和object類型的屬性新值。
映射屬性的setter方法,必須是形如setpropertyname,并且接受兩個參數,string類型的關鍵字和object類型的屬性值。
下面就是設定事件索引和映射屬性的一個示例:
public class myevent{
private mapprops = new hashmap();
privateobject[] array = new object[10];
public voidsetprops(string name, object value) {
props.put(name, value);
}
public voidsetarray(int index, object value) {
array[index] = value;
// ... alsoprovide regular javabean getters and setters for all properties
下面語句是設定索引和映射屬性:
update istreammyeventstream set props('key') = 'abc', array[2] = 100
esper是獲得事件屬性的位元組碼,當位元組碼擷取失敗時,這時候引擎會記錄一個警告并使用java反射機制去獲得屬性值。
一個已知的局限性是,當想獲得一個屬性值,但真實獲得的卻是屬性值子類的對象,引擎就會告警。