
2005年5月25日
最近在弄swing,需要由JComponent生成BufferedImage,在CSDN上發(fā)現(xiàn)一個好例子。下面是范例:
Rectangle?rect?=?comp.getBounds();
?BufferedImage?bufImage?=?new?BufferedImage(rect.width,
???????????rect.height,
???????????BufferedImage.TYPE_INT_RGB);
?Graphics?g?=?bufImage.getGraphics();
?g.translate(-rect.x,?-rect.y);
?comp.paint(g);這樣,JComponent中的圖像就保存到BufferedImage中了。
原文的鏈接:
http://dev.csdn.net/article/13/13531.shtm
posted @
2006-04-14 23:41 小米 閱讀(1386) |
評論 (1) |
編輯 收藏
??????? 好久沒有寫blog了,距離上次寫幾乎已經(jīng)是半年前的事情了。

?這半年發(fā)生了不少事情。首先換了家公司,進(jìn)了家金融企業(yè),每天要西裝革履的,一開始還真是不習(xí)慣。

?這里開發(fā)是用的spring框架,以后要多研究研究spring的東西了。
??????? 第二件事就是和戀愛了三年的女友結(jié)婚了,從此兩人長相廝守,不知道時間久了會不會審美疲勞。呵呵。

??????? 第三件事就是在深圳買了自己的小房子,雖然是小小的兩房,不過我們已經(jīng)很知足了。

?而且剛好是趕在房價大漲前買的,還算走了點運氣。換到現(xiàn)在,都不知道去哪里買好了。
??????? 在這里要向一些留言和發(fā)郵件給我的網(wǎng)友道歉,前段時間實在是太忙,沒有空回復(fù)你們的信息和郵件。請原諒!
posted @
2006-03-29 19:43 小米 閱讀(792) |
評論 (0) |
編輯 收藏
最近真是多事情忙,而且可能要忙到9月底。好久沒有上來更新我的博客了,暫且發(fā)發(fā)牢騷。
posted @
2005-08-10 17:32 小米 閱讀(1186) |
評論 (1) |
編輯 收藏
這一節(jié)是非常實用的一節(jié),我在閱讀此書的時候,一直在迷惑,究竟應(yīng)該怎樣管理Session呢?因為Session的管理是如此重要,類似于以前寫程序?qū)DBC Connection的管理。看完此節(jié)后,終于找到了方法。
在各種Session管理方案中,ThreadLocal模式得到了大量使用。ThreadLocal是Java中一種較為特殊的線程綁定機(jī)制。通過ThreadLocal存取的數(shù)據(jù),總是與當(dāng)前線程相關(guān),也就是說,JVM為每個運行的線程,綁定了私有的本定實例存取空間,從而為多線程環(huán)境經(jīng)常出現(xiàn)的并發(fā)訪問問題提供了一種隔離機(jī)制。
下面是Hibernate官方提供的一個ThreadLocal工具:
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import org.apache.log4j.Logger;


/**//**
* <p>Title: </p>
*
* <p>Description: Session的管理類</p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: </p>
*
* @author George Hill
* @version 1.0
*/


public class HibernateUtil
{

private static final Logger log = Logger.getLogger(HibernateUtil.class);

private static final SessionFactory sessionFactory;


/**//**
* 初始化Hibernate配置
*/

static
{

try
{
// Create the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();

} catch (Throwable ex)
{
log.error("Initial SessionFactory creation failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}

public static final ThreadLocal session = new ThreadLocal();


/**//**
* 根據(jù)當(dāng)前線程獲取相應(yīng)的Session
* @return Session
* @throws HibernateException
*/

public static Session currentSession() throws HibernateException
{
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet

if (s == null)
{
s = sessionFactory.openSession();
session.set(s);
}
return s;
}


/**//**
* 返回Session給相應(yīng)的線程
* @throws HibernateException
*/

public static void closeSession() throws HibernateException
{
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}

}

針對WEB程序,還可以利用Servlet2.3的Filter機(jī)制,輕松實現(xiàn)線程生命周期內(nèi)的Session管理。下面是一個通過Filter進(jìn)行Session管理的典型案例:

public class PersistenceFilter implements Filter
{
protected static ThreadLocal hibernateHolder = new ThreadLocal();


public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
hibernateHolder.set(getSession());

try
{


chain.doFilter(request, response);



} finally
{
Session session = (Session) hibernateHolder.get();

if (session != null)
{
hibernateHolder.set(null);

try
{
session.close();

} catch (HibernateException ex)
{
throw new ServletException(ex);
}
}
}
}


}
posted @
2005-07-29 19:43 小米 閱讀(3942) |
評論 (1) |
編輯 收藏
數(shù)據(jù)分頁顯示,是很多B/S系統(tǒng)會遇到的問題。現(xiàn)在大多數(shù)主流數(shù)據(jù)庫都提供了數(shù)據(jù)部分讀取機(jī)制,而對于某些沒有提供相應(yīng)機(jī)制的數(shù)據(jù)而言,Hibernate也通過其它途徑實現(xiàn)了分頁,如通過Scrollable ResultSet,如果JDBC不支持Scrollable ResultSet,Hibernate也會自動通過ResultSet的next方法進(jìn)行記錄定位。Hibernate的Criteria、Query等接口提供了一致的方法設(shè)定分頁范圍。下面是書中的例子:
Criteria criteria = session.createCriteria(TUser.class);
Criteria.add(Expression.eq("age", "20"));
//從檢索結(jié)果中獲取第100條記錄開始的20條記錄
criteria.setFirstResult(100);
criteria.setFetchSize(20); 不過,我在測試的時候總是不能夠正常工作,把setFetchSize方法換成setMaxResults方法才行。換成最新的mysql-connector-java-3.1.10-bin-g.jar驅(qū)動也是一樣。
posted @
2005-07-26 18:12 小米 閱讀(5558) |
評論 (4) |
編輯 收藏
Hibernate通過Lifecycle、Validatable接口制定了實體對象CRUD過程中的回調(diào)方式。
Lifecycle接口中的onSave、onUpdate、onDelete方法,如果返回true則意味著需要中止執(zhí)行相應(yīng)的操作過程。如果代碼運行期間拋出了CallbackException,對應(yīng)的操作也會被中止。注意,不要試圖在這些方法中調(diào)用Session進(jìn)行持久化操作,這些方法中Session無法正常使用。
Validatable.validate方法將在實體被持久化之前得到調(diào)用以對數(shù)據(jù)進(jìn)行驗證。此方法在實體對象的生命周期內(nèi)可能被數(shù)次調(diào)用,因此,此方法僅用于數(shù)據(jù)本身的邏輯校驗,而不要試圖在此實現(xiàn)業(yè)務(wù)邏輯的驗證。
Hibernate還引入了Interceptor,為持久化事件的捕獲和處理提供了一個非侵略性的實現(xiàn)。Interceptor接口定義了Hibernate中的通用攔截機(jī)制。Session創(chuàng)建時即可指定加載相應(yīng)的Interceptor,之后,此Session的持久化操作動作都將首先經(jīng)由此攔截器捕獲處理。簡單的加載范例如下:
SessionFactory factory = config.buildSessionFactory();
Interceptor it = new MyInterceptor();
session = sessionFactory.openSession(it); 需要注意的是,與Lifecycle相同,Interceptor的方法中不可通過Session實例進(jìn)行持久化操作。
posted @
2005-07-21 18:35 小米 閱讀(3366) |
評論 (1) |
編輯 收藏
有興趣的可以去參加看看,網(wǎng)址:
http://www.javachina.cn/Index.jsp
posted @
2005-07-20 14:55 小米 閱讀(1025) |
評論 (2) |
編輯 收藏
最近真是忙,事情都擠到一塊去了。
終于有時間又看了幾頁書。
言歸正傳,Hibernate中的Collection類型分為有序集和無序集兩類。這里所謂的有序和無序,是針對Hibernate數(shù)據(jù)持久過程中,是否保持?jǐn)?shù)據(jù)集合中的記錄排列順序加以區(qū)分的。無序集有Set,Bag,Map幾種,有序集有List一種。有序集的數(shù)據(jù)在持久化過程中,會將集合中元素排列的先后順序同時固化到數(shù)據(jù)庫中,讀取時也會返回一個具備同樣排列順序的數(shù)據(jù)集合。
Hibernate中的Collection類型是用的自己的實現(xiàn),所以在程序中,不能夠把接口強(qiáng)制轉(zhuǎn)化成相應(yīng)的JDK Collection的實現(xiàn)。
結(jié)果集的排序有兩種方式:
1. Sort
Collection中的數(shù)據(jù)排序。
2. order-by
對數(shù)據(jù)庫執(zhí)行Select SQL時,由order by子句實現(xiàn)的數(shù)據(jù)排序方式。
需要注意的是,order-by特性在實現(xiàn)中借助了JDK 1.4中的新增集合類LinkedHashSet以及LinkedHashMap。因此,order-by特性只支持在1.4版本以上的JDK中運行。
posted @
2005-07-20 10:56 小米 閱讀(3945) |
評論 (0) |
編輯 收藏
Session.get/load的區(qū)別:
1.如果未能發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法會拋出一個ObejctNotFoundException。
2.Load方法可返回實體的代理類類型,而get方法永遠(yuǎn)直接返回實體類。
3.Load方法可以充分利用內(nèi)部緩存和二級緩存中現(xiàn)有數(shù)據(jù),而get方法則僅僅在內(nèi)部緩存中進(jìn)行數(shù)據(jù)查找,如沒有發(fā)現(xiàn)對應(yīng)數(shù)據(jù),將越過二級緩存,直接調(diào)用SQL完成數(shù)據(jù)讀取。
Session.find/iterate的區(qū)別:
find方法將執(zhí)行Select SQL從數(shù)據(jù)庫中獲得所有符合條件的記錄并構(gòu)造相應(yīng)的實體對象,實體對象構(gòu)建完畢之后,就將其納入緩存。它對緩存只寫不讀,因此無法利用緩存。
iterate方法首先執(zhí)行一條Select SQL以獲得所有符合查詢條件的數(shù)據(jù)id,隨即,iterate方法首先在本地緩存中根據(jù)id查找對應(yīng)的實體對象是否存在,如果緩存中已經(jīng)存在對應(yīng)的數(shù)據(jù),則直接以此數(shù)據(jù)對象作為查詢結(jié)果,如果沒有找到,再執(zhí)行相應(yīng)的Select語句獲得對應(yīng)的庫表記錄(iterate方法如果執(zhí)行了數(shù)據(jù)庫讀取操作并構(gòu)建了完整的數(shù)據(jù)對象,也會將其查詢結(jié)果納入緩存)。
Query Cache產(chǎn)生作用的情況:
1.完全相同的Select SQL重復(fù)執(zhí)行。
2.在兩次查詢之間,此Select SQL對應(yīng)的庫表沒有發(fā)生過改變。
Session.save方法的執(zhí)行步驟:
1.在Session內(nèi)部緩存中尋找待保存對象。內(nèi)部緩存命中,則認(rèn)為此數(shù)據(jù)已經(jīng)保存(執(zhí)行過insert操作),實體對象已經(jīng)處于Persistent狀態(tài),直接返回。
2.如果實體類實現(xiàn)了lifecycle接口,則調(diào)用待保存對象的onSave方法。
3.如果實體類實現(xiàn)了validatable接口,則調(diào)用其validate()方法。
4.調(diào)用對應(yīng)攔截器的Interceptor.onSave方法(如果有的話)。
5.構(gòu)造Insert SQL,并加以執(zhí)行。
6.記錄插入成功,user.id屬性被設(shè)定為insert操作返回的新記錄id值。
7.將user對象放入內(nèi)部緩存。
8.最后,如果存在級聯(lián)關(guān)系,對級聯(lián)關(guān)系進(jìn)行遞歸處理。
Session.update方法的執(zhí)行步驟:
1.根據(jù)待更新實體對象的Key,在當(dāng)前session的內(nèi)部緩存中進(jìn)行查找,如果發(fā)現(xiàn),則認(rèn)為當(dāng)前實體對象已經(jīng)處于Persistent狀態(tài),返回。
2.初始化實體對象的狀態(tài)信息(作為之后臟數(shù)據(jù)檢查的依據(jù)),并將其納入內(nèi)部緩存。注意這里Session.update方法本身并沒有發(fā)送Update SQL完成數(shù)據(jù)更新操作,Update SQL將在之后的Session.flush方法中執(zhí)行(Transaction.commit在真正提交數(shù)據(jù)庫事務(wù)之前會調(diào)用Session.flush)。
Session.saveOrUpdate方法的執(zhí)行步驟:
1.首先在Session內(nèi)部緩存中進(jìn)行查找,如果發(fā)現(xiàn)則直接返回。
2.執(zhí)行實體類對應(yīng)的Interceptor.isUnsaved方法(如果有的話),判斷對象是否為未保存狀態(tài)。
3.根據(jù)unsaved-value判斷對象是否處于未保存狀態(tài)。
4.如果對象未保存(Transient狀態(tài)),則調(diào)用save方法保存對象。
5.如果對象為已保存(Detached狀態(tài)),調(diào)用update方法將對象與Session重新關(guān)聯(lián)。
posted @
2005-07-12 18:49 小米 閱讀(4902) |
評論 (5) |
編輯 收藏
事務(wù)的4個基本特性(ACID):
1. Atomic(原子性):事務(wù)中包含的操作被看作一個邏輯單元,這個邏輯單元中的操作要么全部成功,要么全部失敗。
2. Consistency(一致性):只有合法的數(shù)據(jù)可以被寫入數(shù)據(jù)庫,否則事務(wù)應(yīng)該將其回滾到最初狀態(tài)。
3. Isolation(隔離性):事務(wù)允許多個用戶對同一個數(shù)據(jù)的并發(fā)訪問,而不破壞數(shù)據(jù)的正確性和完整性。同時,并行事務(wù)的修改必須與其他并行事務(wù)的修改相互獨立。
4. Durability(持久性):事務(wù)結(jié)束后,事務(wù)處理的結(jié)果必須能夠得到固化。
數(shù)據(jù)庫操作過程中可能出現(xiàn)的3種不確定情況:
1. 臟讀取(Dirty Reads):一個事務(wù)讀取了另一個并行事務(wù)未提交的數(shù)據(jù)。
2. 不可重復(fù)讀取(Non-repeatable Reads):一個事務(wù)再次讀取之前的數(shù)據(jù)時,得到的數(shù)據(jù)不一致,被另一個已提交的事務(wù)修改。
3. 虛讀(Phantom Reads):一個事務(wù)重新執(zhí)行一個查詢,返回的記錄中包含了因為其他最近提交的事務(wù)而產(chǎn)生的新記錄。
標(biāo)準(zhǔn)SQL規(guī)范中,為了避免上面3種情況的出現(xiàn),定義了4個事務(wù)隔離等級:
1. Read Uncommitted:最低等級的事務(wù)隔離,僅僅保證了讀取過程中不會讀取到非法數(shù)據(jù)。上訴3種不確定情況均有可能發(fā)生。
2. Read Committed:大多數(shù)主流數(shù)據(jù)庫的默認(rèn)事務(wù)等級,保證了一個事務(wù)不會讀到另一個并行事務(wù)已修改但未提交的數(shù)據(jù),避免了“臟讀取”。該級別適用于大多數(shù)系統(tǒng)。
3. Repeatable Read:保證了一個事務(wù)不會修改已經(jīng)由另一個事務(wù)讀取但未提交(回滾)的數(shù)據(jù)。避免了“臟讀取”和“不可重復(fù)讀取”的情況,但是帶來了更多的性能損失。
4. Serializable:最高等級的事務(wù)隔離,上面3種不確定情況都將被規(guī)避。這個級別將模擬事務(wù)的串行執(zhí)行。
Hibernate將事務(wù)管理委托給底層的JDBC或者JTA,默認(rèn)是基于JDBC Transaction的。
Hibernate支持“悲觀鎖(Pessimistic Locking)”和“樂觀鎖(Optimistic Locking)”。
悲觀鎖對數(shù)據(jù)被外界修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制。Hibernate通過使用數(shù)據(jù)庫的for update子句實現(xiàn)了悲觀鎖機(jī)制。Hibernate的加鎖模式有:
1. LockMode.NONE:無鎖機(jī)制
2. LockMode.WRITE:Hibernate在Insert和Update記錄的時候會自動獲取
3. LockMode.READ:Hibernate在讀取記錄的時候會自動獲取
4. LockMode.UPGRADE:利用數(shù)據(jù)庫的for update子句加鎖
5. LockMode.UPGRADE_NOWAIT:Oracle的特定實現(xiàn),利用Oracle的for update nowait子句實現(xiàn)加鎖
樂觀鎖大多是基于數(shù)據(jù)版本(Version)記錄機(jī)制實現(xiàn)。Hibernate在其數(shù)據(jù)訪問引擎中內(nèi)置了樂觀鎖實現(xiàn),可以通過class描述符的optimistic-lock屬性結(jié)合version描述符指定。optimistic-lock屬性有如下可選取值:
1. none:無樂觀鎖
2. version:通過版本機(jī)制實現(xiàn)樂觀鎖
3. dirty:通過檢查發(fā)生變動過的屬性實現(xiàn)樂觀鎖
4. all:通過檢查所有屬性實現(xiàn)樂觀鎖
posted @
2005-07-08 16:19 小米 閱讀(4852) |
評論 (4) |
編輯 收藏
現(xiàn)在搜狐新聞上報道已經(jīng)有700多人傷亡,這是自從911事件以后最大的一次恐怖襲擊了。現(xiàn)在這個世界,是越來越不太平了,貧富差距的加大使得恐怖活動有生存的土壤。
不知道世界的經(jīng)濟(jì)會不會隨著這次恐怖襲擊而開始走向蕭條。現(xiàn)在的地球越來越像一個村,發(fā)生在任何一個角落的事情,都有可能會影響到每一個人。
posted @
2005-07-08 10:50 小米 閱讀(660) |
評論 (0) |
編輯 收藏
昨晚偶然看見國際臺播放星戰(zhàn)的作者喬治盧卡斯榮獲AFI終身成就獎的頒獎典禮,耐心的看完了整個頒獎典禮。喬治在發(fā)表致詞的時候,說自己很高興能夠從事自己喜歡的電影工作,如果不拍攝電影,都不知道自己還能夠做什么。拍電影已經(jīng)成了喬治生命的一部分。
看到熒屏上全世界的老人,中年人,年輕人,孩子說著:“Thank you! George.”可以看到喬治的眼睛朦朧。我心中真是感慨,每個人都有自己的夢想,能夠從事自己喜歡的事情,確實是很開心的一件事。而自己所做的工作,能夠給自己帶來快樂,能夠給人們帶來快樂,這樣的工作才值得用一生的時間去從事。
每一個登山者都有著自己心目中最想登上的山頂,能夠登上這個山頂,前面付出的艱辛都是值得的。人生不也如此么?找到自己喜歡從事的事情,用自己畢生的精力去做這件事。
posted @
2005-07-07 12:00 小米 閱讀(662) |
評論 (0) |
編輯 收藏
獻(xiàn)出一份愛心 共同援助重病程序員王俊 |
(2005.06.27) 來自:BJUG |
|
|
|
posted @
2005-07-04 18:48 小米 閱讀(1708) |
評論 (22) |
編輯 收藏
摘要: 要將BufferedImage實例保存為BMP文件,就需要知道BMP文件的格式,可以參考我轉(zhuǎn)載的文章:《BMP文件格式》。 下面是我的將BufferedImage實例保存為24位色BMP文件的實現(xiàn)。 ...
閱讀全文
posted @
2005-07-04 17:33 小米 閱讀(3435) |
評論 (6) |
編輯 收藏
在公元2005年6月27日,我做出了一個重大的決定,買房!花了自己至今為止都沒有見過的那么多的錢買了一個小小的2房2廳,

從此變成了“負(fù)翁”。
不過,從此以后再也不用去租房,再也不用幫別人供房,再也不用一年搬一次家。深圳租房實在太貴,蓮花北的一個小小的二房都要1800,有點裝修就叫豪華裝修,就是一個空蕩蕩的房子也開口要1500,太夸張了。住農(nóng)民房又極度不安全,不想拿自己的生命開玩笑。
從此就變成月供一族了,

,不過,有了壓力才有動力。為了自己的將來,自己的理想,努力奮斗!
9月26日是入伙的日子,好期待那天的到來啊。
posted @
2005-06-29 09:47 小米 閱讀(921) |
評論 (9) |
編輯 收藏
一般而言,ORM的數(shù)據(jù)緩存應(yīng)包含如下幾個層次:
1. 事務(wù)級緩存(Transcation Layer Cache)
2. 應(yīng)用級/進(jìn)程級緩存(Application/Process Layer Cache)
3. 分布式緩存(Cluster Layer Cache)
Hibernate數(shù)據(jù)緩存(Cache)分為兩個層次,以Hibernate語義加以區(qū)分,可分為:
1. 內(nèi)部緩存(Session Level,也稱為一級緩存)
2. 二級緩存(SessionFactory Level,也稱為二級緩存)
Hibernate中,緩存將在以下情況中發(fā)揮作用:
1. 通過id[主鍵]加載數(shù)據(jù)時
2. 延遲加載
內(nèi)部緩存正常情況下由Hibernate自動維護(hù),如果需要手動干預(yù),可以通過以下方法完成:
1. Session.evict
將某個特定對象從內(nèi)部緩存清除。
2. Session.clear
清空內(nèi)部緩存。
在Hibernate中,二級緩存涵蓋了應(yīng)用級緩存和分布式緩存領(lǐng)域。如果數(shù)據(jù)滿足以下條件,則可將其納入緩存管理。
1. 數(shù)據(jù)不會被第三方應(yīng)用修改;
2. 數(shù)據(jù)大小(Data Size)在可接收的范圍之內(nèi);
3. 數(shù)據(jù)更新頻率較低;
4. 同一數(shù)據(jù)可能會被系統(tǒng)頻繁引用;
5. 非關(guān)鍵數(shù)據(jù)(關(guān)鍵數(shù)據(jù),如金融帳戶數(shù)據(jù))。
Hibernate本身并未提供二級緩存的產(chǎn)品化實現(xiàn),而是為眾多的第三方緩存組件提供了接入接口,較常用的第三方組件有:
1. JCS
2. EHCache
3. OSCache
4. JBossCache
5. SwarmCache
Hibernate中啟用二級緩存,需要在hibernate.cfg.xml配置hibernate.cache.provider_class參數(shù),之后,需要在映射文件中指定各個映射實體(以及collection)的緩存同步策略。Hibernate提供了一下4種內(nèi)置的緩存同步策略:
1. read-only
只讀。對于不會發(fā)生改變的數(shù)據(jù),可使用只讀型緩存。
2. nonstrict-read-write
如果程序?qū)Σl(fā)訪問下的數(shù)據(jù)同步要求不是非常嚴(yán)格,且數(shù)據(jù)更新操作頻率較低,可以采用本選項,獲得較好的性能。
3. read-write
嚴(yán)格可讀寫緩存。基于時間戳判定機(jī)制,實現(xiàn)了“read committed”事務(wù)隔離等級。可用于對數(shù)據(jù)同步要求嚴(yán)格的情況,但不支持分布式緩存。這也是實際應(yīng)用中使用最多的同步策略。
4. transactional
事務(wù)型緩存,必須運行在JTA事務(wù)環(huán)境中。
posted @
2005-06-22 18:15 小米 閱讀(6110) |
評論 (5) |
編輯 收藏
在Java語言中,對象之間的比較可以通過引用比較(==)和內(nèi)容比較(equals)兩種方式進(jìn)行,而在Hibernate的實體對象的比較是通過主鍵值來比較,如果要實現(xiàn)自己的識別邏輯,則需要重寫equals方法和hashCode方法。
檢查數(shù)據(jù)對象改變檢查的一般策略有下面兩種:
1. 數(shù)據(jù)對象監(jiān)控
數(shù)據(jù)對象監(jiān)控的實現(xiàn)方式,通過攔截器對數(shù)據(jù)對象的設(shè)值方法進(jìn)行攔截。一旦數(shù)據(jù)對象的設(shè)置方法被調(diào)用,則將其標(biāo)志為“待更新”狀態(tài),之后在數(shù)據(jù)庫操作時將其更新到對應(yīng)的庫表。
2. 數(shù)據(jù)版本對比
在持久層框架中維持?jǐn)?shù)據(jù)對象的最近讀取版本,當(dāng)數(shù)據(jù)提交時將提交數(shù)據(jù)與此版本進(jìn)行比對,如果發(fā)生變化則將其同步到數(shù)據(jù)庫對應(yīng)的庫表。
Hibernate采取的是第二種檢查策略。它采用一個內(nèi)部數(shù)據(jù)結(jié)構(gòu)"EntityEntry"保存對應(yīng)實體類的狀態(tài)信息。
對于級聯(lián)對象的更新,Hibernate將根據(jù)unsaved-value進(jìn)行判定。首先Hibernate會取出目標(biāo)對象的id。之后,將此值與unsaved-value進(jìn)行比對,如果相等,則認(rèn)為目標(biāo)對象尚未保存,否則,認(rèn)為對象已經(jīng)保存,無需再進(jìn)行保存操作。
posted @
2005-06-22 16:32 小米 閱讀(5160) |
評論 (4) |
編輯 收藏
最近正在研讀《深入淺出Hibernate》一書,前面寫的隨筆有些也是讀該書的筆記,只是未做歸類,從這篇開始,我將把相關(guān)的內(nèi)容都整理成一個系列的讀書筆記。
今天這篇是有關(guān)實體對象的生命周期。我剛開始接觸Hibernate的時候,只是簡單的把它當(dāng)做一個API工具,直到后來看到有關(guān)VO和PO的內(nèi)容時,才意識到Hibernate不僅僅是一個O/R Mapping的API工具,它還是一個容器。它可以幫你管理實體對象的生命周期。
實體對象的生命周期有三種狀態(tài):
1.Transient(自由狀態(tài))
此時的實體對象和數(shù)據(jù)庫中的記錄無關(guān)聯(lián),只是一個普通的JavaBean。
2.Persistent(持久狀態(tài))
此時的實體對象和數(shù)據(jù)庫中的記錄有關(guān)聯(lián),其變更將由Hibernate固化到數(shù)據(jù)庫中。該實體對象處于由Hibernate框架所管理的狀態(tài)。
3.Detached(游離狀態(tài))
處于Persistent狀態(tài)的對象,其對應(yīng)的Session實例關(guān)閉之后,那么,此對象就處于"Detached"狀態(tài)。Detached狀態(tài)和Transient狀態(tài)的區(qū)別在于Detached狀態(tài)的對象可以再次與某個Session實例相關(guān)聯(lián)而成為Persistent對象。
從實體對象是否被納入Hibernate實體管理容器的角度,Transient和Detached狀態(tài)的實體對象可以統(tǒng)稱為VO(Value Object),而被管理的實體對象稱為PO(Persistent Object)。兩者的區(qū)別:
1.VO是相對獨立的實體對象,處于非管理狀態(tài)。
2.PO是Hibernate納入其實體管理容器(Entity Map)的對象,它代表了與數(shù)據(jù)庫中某條記錄對應(yīng)的Hibernate實體,PO的變化在事務(wù)提交時將反映到實際數(shù)據(jù)庫中。
3.如果一個PO與其對應(yīng)的Session實例分離,那么此時,它又會變成一個VO。
下圖是我畫的實體對象生命周期的狀態(tài)轉(zhuǎn)換圖:
posted @
2005-06-16 18:31 小米 閱讀(3082) |
評論 (9) |
編輯 收藏
在使用HQL查詢中,有時并不需要獲取完整的一個實體對象,例如一個實體對象User有三個屬性:account, password和email,如果我們只需要獲取account和email屬性,那么有兩種方法可以選擇。
1. 用普通的"select user.account, user.email from User as user",程序片斷如下:
List list = session.createQuery("select user.account, user.email from User as user").list();
Iterator it = list.iterator();

while (it.hasNext())
{
Object[] values = (Object[]) it.next();
System.out.println(values[0] + " " + values[1]);
} 這時調(diào)用Query類的list方法返回的將是一個每個元素都是一個Object數(shù)組的List。如果只獲取一個屬性,那么返回的List中的每個元素都是String實例。
2.在HQL中用new操作符生成實體對象,例如:"select new User(user.account, user.email) from User as user",程序片斷如下:
List list = session.createQuery("select new User(user.account, user.email) from User as user").list();
Iterator it = list.iterator();

while (it.hasNext())
{
User user = (User) it.next();
System.out.println(user.getAccount() + " " + user.getEmail());
} 這時list方法返回的List中的每一個元素都是User實體對象。這里有三點需要注意的:
a.在HQL語句中需要使用as操作符指定User的別名,并且需要在構(gòu)造函數(shù)的屬性前面加上別名;
b.HQL語句中的構(gòu)造函數(shù)在User類中必須要有相應(yīng)的構(gòu)造函數(shù);
c.生成的實體對象是VO對象,如果對這些對象調(diào)用Session的saveOrUpdate方法將導(dǎo)致插入新的記錄,而不是更新記錄。
posted @
2005-06-15 16:33 小米 閱讀(2999) |
評論 (0) |
編輯 收藏
JBuilder 2005中多了一個Smart MemberInsight功能,這個功能會智能的匹配需要調(diào)用的方法或者獲取的屬性。例如有一個賦值操作,左邊是一個List,右邊是用一個方法獲取值,那么當(dāng)輸入"."時,JBuilder 2005會自動的找到所有返回的值為List的方法。
不過,這實在是一個不怎么討好的方法。因為很多時候并不是只有一層方法調(diào)用的,例如,當(dāng)需要用一個方法獲取一個實例,然后再用這個實例的方法獲取需要的值時,這個功能就顯得很礙手了。
終于,我還是決定關(guān)閉這個“智能”的功能。打開"Tools"——>"Preferences",在"Editor"的子項"CodeInsight"里,展開"MemberInsight",把"Default to Smart MemberInsight"這一項去掉。如下圖所示:
posted @
2005-06-15 16:02 小米 閱讀(524) |
評論 (0) |
編輯 收藏
這個范例說明如何用JFreeChart畫簡單的柱狀圖,下面是一個JSP的簡單范例:
<%@ page contentType="text/html; charset=GB2312" %>
<%@ page import="java.awt.*, java.text.*, java.util.*" %>
<%@ page import="org.jfree.chart.*" %>
<%@ page import="org.jfree.chart.axis.*" %>
<%@ page import="org.jfree.chart.labels.StandardCategoryItemLabelGenerator" %>
<%@ page import="org.jfree.chart.plot.*" %>
<%@ page import="org.jfree.chart.renderer.*" %>
<%@ page import="org.jfree.chart.servlet.ServletUtilities" %>
<%@ page import="org.jfree.data.DefaultCategoryDataset" %>
<%@ page import="org.jfree.ui.TextAnchor" %>

<%
//The data for the bar chart

double[] data =
{85, 156, 179.5, 211, 123};
//The labels for the bar chart

String[] labels =
{"Mon", "Tue", "Wed", "Thu", "Fri"};
DefaultCategoryDataset dataset = new DefaultCategoryDataset();

for (int i = 0; i < data.length; i++)
{
dataset.addValue(data[i], null, labels[i]);
}
JFreeChart chart = ChartFactory.createBarChart3D("Weekly Server Load", "Work Week 25", "MBytes", dataset, PlotOrientation.VERTICAL, false, false, false);
chart.setBackgroundPaint(new Color(0xE1E1E1));
CategoryPlot plot = chart.getCategoryPlot();
// 設(shè)置Y軸顯示整數(shù)
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
CategoryAxis domainAxis = plot.getDomainAxis();
//設(shè)置距離圖片左端距離
domainAxis.setLowerMargin(0.05);
BarRenderer3D renderer = new BarRenderer3D();
//設(shè)置柱的顏色
renderer.setSeriesPaint(0, new Color(0xff00));
plot.setRenderer(renderer);
String filename = ServletUtilities.saveChartAsPNG(chart, 300, 280, null, session);
String graphURL = request.getContextPath() + "/displayChart?filename=" + filename;
%>
<html>
<body topmargin="5" leftmargin="5" rightmargin="0">
<div style="font-size:18pt; font-family:verdana; font-weight:bold">
3D Bar Chart
</div>
<br>
<img src="<%= graphURL %>" border=0>
</body>
</html>

畫出來的圖:

和ChartDirector畫出來的圖做一個比較:

posted @
2005-06-14 18:40 小米 閱讀(10693) |
評論 (7) |
編輯 收藏
以前一直是用JFreeChart畫統(tǒng)計圖的,不過JFreeChart畫出來的圖形不夠精細(xì),看起來有些模糊,今天在網(wǎng)上看到另外一個工具ChartDirector,這是一個商業(yè)版本的工具,不過也可以免費使用,只是在畫出來的圖形下面都有一條它的廣告條。
下面是它的一個柱狀圖的例子:

范例程序:
<%@page import="ChartDirector.*" %>
<%
//The data for the bar chart

double[] data =
{85, 156, 179.5, 211, 123};

//The labels for the bar chart

String[] labels =
{"Mon", "Tue", "Wed", "Thu", "Fri"};

//Create a XYChart object of size 300 x 280 pixels
XYChart c = new XYChart(300, 280);

//Set the plotarea at (45, 30) and of size 200 x 200 pixels
c.setPlotArea(45, 30, 200, 200);

//Add a title to the chart
c.addTitle("Weekly Server Load");

//Add a title to the y axis
c.yAxis().setTitle("MBytes");

//Add a title to the x axis
c.xAxis().setTitle("Work Week 25");

//Add a bar chart layer with green (0x00ff00) bars using the given data
c.addBarLayer(data, 0xff00).set3D();

//Set the labels on the x axis.
c.xAxis().setLabels(labels);

//output the chart
String chart1URL = c.makeSession(request, "chart1");

//include tool tip for the chart
String imageMap1 = c.getHTMLImageMap("", "", "title='{xLabel}: {value} MBytes'")
;
%>
<html>
<body topmargin="5" leftmargin="5" rightmargin="0">
<div style="font-size:18pt; font-family:verdana; font-weight:bold">
3D Bar Chart
</div>
<hr color="#000080">
<a href="viewsource.jsp?file=<%=request.getServletPath()%>">
<font size="2" face="Verdana">View Chart Source Code</font>
</a>
</div>
<br>
<img src='<%=response.encodeURL("getchart.jsp?"+chart1URL)%>'
usemap="#map1" border="0">
<map name="map1"><%=imageMap1%></map>
</body>
</html>

如果要在柱的頂部顯示數(shù)值,可以調(diào)用Layer的setDataLabelFormat方法設(shè)置,范例:layer.setDataLabelFormat("{value}");
其它的例子可以參考它的文檔的說明。ChartDirector的網(wǎng)址:http://www.advsofteng.com
posted @
2005-06-14 17:46 小米 閱讀(5246) |
評論 (5) |
編輯 收藏
如果要在程序中定時執(zhí)行任務(wù),可以使用java.util.Timer這個類實現(xiàn)。使用Timer類需要一個繼承了java.util.TimerTask的類。TimerTask是一個虛類,需要實現(xiàn)它的run方法,實際上是他implements了Runnable接口,而把run方法留給子類實現(xiàn)。
下面是我的一個例子:

class Worker extends TimerTask
{

public void run()
{
System.out.println("我在工作啦!");
}
} Timer類用schedule方法或者scheduleAtFixedRate方法啟動定時執(zhí)行,schedule重載了四個版本,scheduleAtFixedRate重載了兩個。每個方法的實現(xiàn)都不同,下面是每個方法的說明:
schedule
public void schedule(TimerTask task,
long delay)
- Schedules the specified task for execution after the specified delay.
-
- Parameters:
task
- task to be scheduled.
delay
- delay in milliseconds before task is to be executed.
- Throws:
IllegalArgumentException
- if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException
- if task was already scheduled or cancelled, or timer was cancelled.
說明:該方法會在設(shè)定的延時后執(zhí)行一次任務(wù)。
schedule
public void schedule(TimerTask task,
Date time)
- Schedules the specified task for execution at the specified time. If the time is in the past, the task is scheduled for immediate execution.
-
- Parameters:
task
- task to be scheduled.
time
- time at which task is to be executed.
- Throws:
IllegalArgumentException
- if time.getTime() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說明:該方法會在指定的時間點執(zhí)行一次任務(wù)。
schedule
public void schedule(TimerTask task,
long delay,
long period)
- Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals separated by the specified period.
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other words, it is appropriate for activities where it is more important to keep the frequency accurate in the short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It also includes tasks wherein regular activity is performed in response to human input, such as automatically repeating a character as long as a key is held down.
-
- Parameters:
task
- task to be scheduled.
delay
- delay in milliseconds before task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說明:該方法會在指定的延時后執(zhí)行任務(wù),并且在設(shè)定的周期定時執(zhí)行任務(wù)。
schedule
public void schedule(TimerTask task,
Date firstTime,
long period)
- Schedules the specified task for repeated fixed-delay execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-delay execution is appropriate for recurring activities that require "smoothness." In other words, it is appropriate for activities where it is more important to keep the frequency accurate in the short run than in the long run. This includes most animation tasks, such as blinking a cursor at regular intervals. It also includes tasks wherein regular activity is performed in response to human input, such as automatically repeating a character as long as a key is held down.
-
- Parameters:
task
- task to be scheduled.
firstTime
- First time at which task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if time.getTime() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說明:該方法會在指定的時間點執(zhí)行任務(wù),然后從該時間點開始,在設(shè)定的周期定時執(zhí)行任務(wù)。特別的,如果設(shè)定的時間點在當(dāng)前時間之前,任務(wù)會被馬上執(zhí)行,然后開始按照設(shè)定的周期定時執(zhí)行任務(wù)。
scheduleAtFixedRate
public void scheduleAtFixedRate(TimerTask task,
long delay,
long period)
- Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay. Subsequent executions take place at approximately regular intervals, separated by the specified period.
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. It is also appropriate for recurring activities where the total time to perform a fixed number of executions is important, such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
-
- Parameters:
task
- task to be scheduled.
delay
- delay in milliseconds before task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if delay is negative, or delay + System.currentTimeMillis() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說明:該方法和schedule的相同參數(shù)的版本類似,不同的是,如果該任務(wù)因為某些原因(例如垃圾收集)而延遲執(zhí)行,那么接下來的任務(wù)會盡可能的快速執(zhí)行,以趕上特定的時間點。
scheduleAtFixedRate
public void scheduleAtFixedRate(TimerTask task,
Date firstTime,
long period)
- Schedules the specified task for repeated fixed-rate execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time. It is also appropriate for recurring activities where the total time to perform a fixed number of executions is important, such as a countdown timer that ticks once every second for ten seconds. Finally, fixed-rate execution is appropriate for scheduling multiple repeating timer tasks that must remain synchronized with respect to one another.
-
- Parameters:
task
- task to be scheduled.
firstTime
- First time at which task is to be executed.
period
- time in milliseconds between successive task executions.
- Throws:
IllegalArgumentException
- if time.getTime() is negative.
IllegalStateException
- if task was already scheduled or cancelled, timer was cancelled, or timer thread terminated.
說明:和上一個方法類似。
下面是我的一個測試片斷:

public static void main(String[] args) throws Exception
{
Timer timer = new Timer(false);
timer.schedule(new Worker(), new Date(System.currentTimeMillis() + 1000));
}
posted @
2005-06-09 10:29 小米 閱讀(33745) |
評論 (7) |
編輯 收藏
今天得知,現(xiàn)在住的房子,公司要準(zhǔn)備拍賣了,那就是說,我又要搬家了。
這將是我大學(xué)畢業(yè)后的第四次搬家了,每年搬一次家,有時候真的厭倦了這樣的生活,剛適應(yīng)一個環(huán)境,又要重新去適應(yīng)新的環(huán)境。好想擁有自己的房子,但是現(xiàn)在深圳的房價卻讓人望樓興嘆!
什么時候才能夠讓老百姓過上安居樂業(yè)的生活。
《我想有個家》,潘美辰的這首老歌,現(xiàn)在最能夠代表我的心情了。
posted @
2005-06-06 21:49 小米 閱讀(550) |
評論 (4) |
編輯 收藏
Criteria Query是很好的一種面向?qū)ο蟮牟樵儗崿F(xiàn),它提供了一種示例查詢的方式。該方式根據(jù)已有的對象,查找數(shù)據(jù)庫中屬性匹配的其他對象。
下面是一個場景片斷,模糊查找數(shù)據(jù)庫中用戶帳號為'test',郵件地址為
'georgehill@21cn.com'的實例,忽略大小寫。

public void testCriteriaExampleQuery() throws Exception
{
User user = new User();
user.setAccount("test");
user.setEmail("georgehill@21cn.com");
Criteria criteria = session.createCriteria(User.class).add(Example.create(user).enableLike(MatchMode.ANYWHERE).ignoreCase());
List list = criteria.list();

if (list != null)
{

for (int i = 0; i < list.size(); i++)
{
System.out.println(((User) list.get(i)).getAccount());
}
}
} 示例查詢需要生成Example實例,可以通過Example的靜態(tài)方法create生成。Example類有下面的幾個方法指定查詢的方式:
excludeZeroes
public Example excludeZeroes()
- Exclude zero-valued properties
-
excludeNone
public Example excludeNone()
- Don't exclude null or zero-valued properties
-
enableLike
public Example enableLike(MatchMode matchMode)
- Use the "like" operator for all string-valued properties
-
enableLike
public Example enableLike()
- Use the "like" operator for all string-valued properties
-
ignoreCase
public Example ignoreCase()
- Ignore case for all string-valued properties
-
excludeProperty
public Example excludeProperty(String name)
- Exclude a particular named property
-
當(dāng)用enableLike()方法時,可以通過MatchMode指定匹配的方式。MatchMode提供了四種匹配的方式:
posted @
2005-06-03 17:27 小米 閱讀(2187) |
評論 (3) |
編輯 收藏
摘要: 利用JavaMail的API可以快速的實現(xiàn)發(fā)送郵件的功能。下面是我使用的一個簡單的實例,實現(xiàn)了簡單的文本郵件的發(fā)送。
import java.io.*;import java.util.*;import javax.activation.*;import javax.mail.*;...
閱讀全文
posted @
2005-06-02 16:30 小米 閱讀(2217) |
評論 (7) |
編輯 收藏
好懷念以前可以過六一兒童節(jié)的時候,可以放假,學(xué)校還會組織活動,每到這天,都可以名正言順的出去玩。呵呵。現(xiàn)在可沒有六一兒童節(jié)過了。
posted @
2005-06-01 16:29 小米 閱讀(442) |
評論 (0) |
編輯 收藏
上個月過了理論考試,昨天終于第一次開起了汽車。呵呵,一開始好緊張啊,給師傅狂罵。

有兩次還差點撞到墻。

后來熟悉了后,就好了很多了。呵呵,第一天學(xué)會了怎么啟動,停車,打檔和轉(zhuǎn)方向盤。上手還是很快滴!

不過,想起要上路,我就感覺恐怖。
posted @
2005-05-26 10:21 小米 閱讀(483) |
評論 (0) |
編輯 收藏
以前在寫程序的時候,碰到需要比較兩個有可能為null的實例時,為了避免出現(xiàn)NullPointerException,經(jīng)常用這樣的一段代碼來比較:
Object obj1 = "abc";
Object obj2 = "cde";
if ((obj1 == null && obj2 == null) || (obj1 != null && obj1.equals(obj2))

|| (obj2 != null && obj2.equals(obj1)))
{
System.out.println("equals");
} 這樣的程序,讀起來真是挺拗口。我一直沒有想到什么好的方法解決這個問題,直到今天在看到JDK的AbstractList源碼的equals方法的實現(xiàn)時,看到這一段:
if (!(o1==null ? o2==null : o1.equals(o2)))
return false; 原來用三元運算符可以很好的解決這個問題,呵呵,我前面的程序可以改寫成:
Object obj1 = "abc";
Object obj2 = "cde";
if (obj1 == null ? obj2 == null : obj1.equals(obj2))
System.out.println("equals"); 真是簡潔多了!
posted @
2005-05-25 17:00 小米 閱讀(1342) |
評論 (0) |
編輯 收藏
從對象池中獲取的實例,因為并不清楚該channel是否已經(jīng)設(shè)置成正確的狀態(tài),所以在使用時最好重新設(shè)置一遍。有以下幾點需要注意:
1.在使用阻塞IO時,需要把該channel設(shè)置成阻塞的,即需要調(diào)用SocketChannel.configureBlocking(true);
2.在使用非阻塞IO時,需要把該channel設(shè)置成非阻塞的,即需要調(diào)用SocketChannel.configureBlocking(false);
3.如果該channel注冊了selector,那么在返回該實例到對象池中,需要把注冊的selector清除,即需要調(diào)用Selector的close方法。
下面是一段應(yīng)用場景的例子:


// 把命令輸出
channel.configureBlocking(true);
PrintWriter writer = new PrintWriter(channel.socket().getOutputStream(), false);
writer.write(command.endsWith("\n") ? command : command + "\n");
writer.flush();

channel.configureBlocking(false);

// 創(chuàng)建Selector
Selector selector = Selector.open();
// 向Selector注冊我們需要的READ事件
SelectionKey skey = channel.register(selector, SelectionKey.OP_READ);

boolean stop = false;
int n = 0;
int read = 0;
ByteBuffer buffer = ByteBuffer.allocate(1024);

// 輪詢

while (!stop)
{
// 獲取Selector返回的時間值
n = selector.select();

// 當(dāng)傳回的值大于0事,讀事件發(fā)生了

if (n > 0)
{
// 處理發(fā)生的事件

}
}

selector.close();
posted @
2005-05-25 15:02 小米 閱讀(3202) |
評論 (0) |
編輯 收藏