随笔-57  评论-202  文章-17  trackbacks-0
  2005年7月4日
最近在弄swing,需要由JComponent生成BufferedImage,在CSDN上发现一个好例子。下面是范例:

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 小米 阅读(1357) | 评论 (1)编辑 收藏
        好久没有写blog了,距离上次写几乎已经是半年前的事情了。 这半年发生了不少事情。首先换了家公司,进了家金融企业,每天要西装革履的,一开始还真是不习惯。 这里开发是用的spring框架,以后要多研究研究spring的东西了。
        第二件事就是和恋爱了三年的女友结婚了,从此两人长相厮守,不知道时间久了会不会审美疲劳。呵呵。
        第三件事就是在深圳买了自己的小房子,虽然是小小的两房,不过我们已经很知足了。 而且刚好是赶在房价大涨前买的,还算走了点运气。换到现在,都不知道去哪里买好了。
        在这里要向一些留言和发邮件给我的网友道歉,前段时间实在是太忙,没有空回复你们的信息和邮件。请原谅!
posted @ 2006-03-29 19:43 小米 阅读(763) | 评论 (0)编辑 收藏
      最近真是多事情忙,而且可能要忙到9月底。好久没有上来更新我的博客了,暂且发发牢骚。
posted @ 2005-08-10 17:32 小米 阅读(1173) | 评论 (1)编辑 收藏
      这一节是非常实用的一节,我在阅读此书的时候,一直在迷惑,究竟应该怎样管理Session呢?因为Session的管理是如此重要,类似于以前写程序对JDBC Connection的管理。看完此节后,终于找到了方法。
      在各种Session管理方案中,ThreadLocal模式得到了大量使用。ThreadLocal是Java中一种较为特殊的线程绑定机制。通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM为每个运行的线程,绑定了私有的本定实例存取空间,从而为多线程环境经常出现的并发访问问题提供了一种隔离机制。
      下面是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();

  
/**
   * 根据当前线程获取相应的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给相应的线程
   * @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机制,轻松实现线程生命周期内的Session管理。下面是一个通过Filter进行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 小米 阅读(3926) | 评论 (1)编辑 收藏
      数据分页显示,是很多B/S系统会遇到的问题。现在大多数主流数据库都提供了数据部分读取机制,而对于某些没有提供相应机制的数据而言,Hibernate也通过其它途径实现了分页,如通过Scrollable ResultSet,如果JDBC不支持Scrollable ResultSet,Hibernate也会自动通过ResultSet的next方法进行记录定位。Hibernate的Criteria、Query等接口提供了一致的方法设定分页范围。下面是书中的例子:

Criteria criteria = session.createCriteria(TUser.class);
Criteria.add(Expression.eq(
"age""20"));
//从检索结果中获取第100条记录开始的20条记录
criteria.setFirstResult(100);
criteria.setFetchSize(
20);

      不过,我在测试的时候总是不能够正常工作,把setFetchSize方法换成setMaxResults方法才行。换成最新的mysql-connector-java-3.1.10-bin-g.jar驱动也是一样。
posted @ 2005-07-26 18:12 小米 阅读(5529) | 评论 (4)编辑 收藏

      Hibernate通过Lifecycle、Validatable接口制定了实体对象CRUD过程中的回调方式。
      Lifecycle接口中的onSave、onUpdate、onDelete方法,如果返回true则意味着需要中止执行相应的操作过程。如果代码运行期间抛出了CallbackException,对应的操作也会被中止。注意,不要试图在这些方法中调用Session进行持久化操作,这些方法中Session无法正常使用。
      Validatable.validate方法将在实体被持久化之前得到调用以对数据进行验证。此方法在实体对象的生命周期内可能被数次调用,因此,此方法仅用于数据本身的逻辑校验,而不要试图在此实现业务逻辑的验证。



      Hibernate还引入了Interceptor,为持久化事件的捕获和处理提供了一个非侵略性的实现。Interceptor接口定义了Hibernate中的通用拦截机制。Session创建时即可指定加载相应的Interceptor,之后,此Session的持久化操作动作都将首先经由此拦截器捕获处理。简单的加载范例如下:

SessionFactory factory = config.buildSessionFactory();
Interceptor it 
= new MyInterceptor();
session 
= sessionFactory.openSession(it);

      需要注意的是,与Lifecycle相同,Interceptor的方法中不可通过Session实例进行持久化操作。
posted @ 2005-07-21 18:35 小米 阅读(3350) | 评论 (1)编辑 收藏
      有兴趣的可以去参加看看,网址:http://www.javachina.cn/Index.jsp
posted @ 2005-07-20 14:55 小米 阅读(1012) | 评论 (2)编辑 收藏

      最近真是忙,事情都挤到一块去了。 终于有时间又看了几页书。
      言归正传,Hibernate中的Collection类型分为有序集和无序集两类。这里所谓的有序和无序,是针对Hibernate数据持久过程中,是否保持数据集合中的记录排列顺序加以区分的。无序集有Set,Bag,Map几种,有序集有List一种。有序集的数据在持久化过程中,会将集合中元素排列的先后顺序同时固化到数据库中,读取时也会返回一个具备同样排列顺序的数据集合。
      Hibernate中的Collection类型是用的自己的实现,所以在程序中,不能够把接口强制转化成相应的JDK Collection的实现。



      结果集的排序有两种方式:
      1. Sort
         Collection中的数据排序。
      2. order-by
         对数据库执行Select SQL时,由order by子句实现的数据排序方式。

      需要注意的是,order-by特性在实现中借助了JDK 1.4中的新增集合类LinkedHashSet以及LinkedHashMap。因此,order-by特性只支持在1.4版本以上的JDK中运行。

posted @ 2005-07-20 10:56 小米 阅读(3929) | 评论 (0)编辑 收藏
      Session.get/load的区别:
      1.如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObejctNotFoundException。
      2.Load方法可返回实体的代理类类型,而get方法永远直接返回实体类。
      3.Load方法可以充分利用内部缓存和二级缓存中现有数据,而get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。



      Session.find/iterate的区别:
      find方法将执行Select SQL从数据库中获得所有符合条件的记录并构造相应的实体对象,实体对象构建完毕之后,就将其纳入缓存。它对缓存只写不读,因此无法利用缓存。
      iterate方法首先执行一条Select SQL以获得所有符合查询条件的数据id,随即,iterate方法首先在本地缓存中根据id查找对应的实体对象是否存在,如果缓存中已经存在对应的数据,则直接以此数据对象作为查询结果,如果没有找到,再执行相应的Select语句获得对应的库表记录(iterate方法如果执行了数据库读取操作并构建了完整的数据对象,也会将其查询结果纳入缓存)。



      Query Cache产生作用的情况:
      1.完全相同的Select SQL重复执行。
      2.在两次查询之间,此Select SQL对应的库表没有发生过改变。



      Session.save方法的执行步骤:
      1.在Session内部缓存中寻找待保存对象。内部缓存命中,则认为此数据已经保存(执行过insert操作),实体对象已经处于Persistent状态,直接返回。
      2.如果实体类实现了lifecycle接口,则调用待保存对象的onSave方法。
      3.如果实体类实现了validatable接口,则调用其validate()方法。
      4.调用对应拦截器的Interceptor.onSave方法(如果有的话)。
      5.构造Insert SQL,并加以执行。
      6.记录插入成功,user.id属性被设定为insert操作返回的新记录id值。
      7.将user对象放入内部缓存。
      8.最后,如果存在级联关系,对级联关系进行递归处理。



      Session.update方法的执行步骤:
      1.根据待更新实体对象的Key,在当前session的内部缓存中进行查找,如果发现,则认为当前实体对象已经处于Persistent状态,返回。
      2.初始化实体对象的状态信息(作为之后脏数据检查的依据),并将其纳入内部缓存。注意这里Session.update方法本身并没有发送Update SQL完成数据更新操作,Update SQL将在之后的Session.flush方法中执行(Transaction.commit在真正提交数据库事务之前会调用Session.flush)。


      Session.saveOrUpdate方法的执行步骤:
      1.首先在Session内部缓存中进行查找,如果发现则直接返回。
      2.执行实体类对应的Interceptor.isUnsaved方法(如果有的话),判断对象是否为未保存状态。
      3.根据unsaved-value判断对象是否处于未保存状态。
      4.如果对象未保存(Transient状态),则调用save方法保存对象。
      5.如果对象为已保存(Detached状态),调用update方法将对象与Session重新关联。

posted @ 2005-07-12 18:49 小米 阅读(4879) | 评论 (5)编辑 收藏
      事务的4个基本特性(ACID):
      1. Atomic(原子性):事务中包含的操作被看作一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。
      2. Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。
      3. Isolation(隔离性):事务允许多个用户对同一个数据的并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
      4. Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。

      数据库操作过程中可能出现的3种不确定情况:
      1. 脏读取(Dirty Reads):一个事务读取了另一个并行事务未提交的数据。
      2. 不可重复读取(Non-repeatable Reads):一个事务再次读取之前的数据时,得到的数据不一致,被另一个已提交的事务修改。
      3. 虚读(Phantom Reads):一个事务重新执行一个查询,返回的记录中包含了因为其他最近提交的事务而产生的新记录。

      标准SQL规范中,为了避免上面3种情况的出现,定义了4个事务隔离等级:
      1. Read Uncommitted:最低等级的事务隔离,仅仅保证了读取过程中不会读取到非法数据。上诉3种不确定情况均有可能发生。
      2. Read Committed:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
      3. Repeatable Read:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
      4. Serializable:最高等级的事务隔离,上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。

      Hibernate将事务管理委托给底层的JDBC或者JTA,默认是基于JDBC Transaction的。
      Hibernate支持“悲观锁(Pessimistic Locking)”和“乐观锁(Optimistic Locking)”。
      悲观锁对数据被外界修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制。Hibernate通过使用数据库的for update子句实现了悲观锁机制。Hibernate的加锁模式有:
      1. LockMode.NONE:无锁机制
      2. LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取
      3. LockMode.READ:Hibernate在读取记录的时候会自动获取
      4. LockMode.UPGRADE:利用数据库的for update子句加锁
      5. LockMode.UPGRADE_NOWAIT:Oracle的特定实现,利用Oracle的for update nowait子句实现加锁
      乐观锁大多是基于数据版本(Version)记录机制实现。Hibernate在其数据访问引擎中内置了乐观锁实现,可以通过class描述符的optimistic-lock属性结合version描述符指定。optimistic-lock属性有如下可选取值:
      1. none:无乐观锁
      2. version:通过版本机制实现乐观锁
      3. dirty:通过检查发生变动过的属性实现乐观锁
      4. all:通过检查所有属性实现乐观锁
posted @ 2005-07-08 16:19 小米 阅读(4830) | 评论 (4)编辑 收藏

      现在搜狐新闻上报道已经有700多人伤亡,这是自从911事件以后最大的一次恐怖袭击了。现在这个世界,是越来越不太平了,贫富差距的加大使得恐怖活动有生存的土壤。
      不知道世界的经济会不会随着这次恐怖袭击而开始走向萧条。现在的地球越来越像一个村,发生在任何一个角落的事情,都有可能会影响到每一个人。

posted @ 2005-07-08 10:50 小米 阅读(646) | 评论 (0)编辑 收藏
      昨晚偶然看见国际台播放星战的作者乔治卢卡斯荣获AFI终身成就奖的颁奖典礼,耐心的看完了整个颁奖典礼。乔治在发表致词的时候,说自己很高兴能够从事自己喜欢的电影工作,如果不拍摄电影,都不知道自己还能够做什么。拍电影已经成了乔治生命的一部分。
      看到荧屏上全世界的老人,中年人,年轻人,孩子说着:“Thank you! George.”可以看到乔治的眼睛朦胧。我心中真是感慨,每个人都有自己的梦想,能够从事自己喜欢的事情,确实是很开心的一件事。而自己所做的工作,能够给自己带来快乐,能够给人们带来快乐,这样的工作才值得用一生的时间去从事。
      每一个登山者都有着自己心目中最想登上的山顶,能够登上这个山顶,前面付出的艰辛都是值得的。人生不也如此么?找到自己喜欢从事的事情,用自己毕生的精力去做这件事。
posted @ 2005-07-07 12:00 小米 阅读(645) | 评论 (0)编辑 收藏
献出一份爱心 共同援助重病程序员王俊
(2005.06.27)   来自:BJUG  
 

向IT界倡议:援助程序员王俊行动

王俊,今年27岁,北京北方银证公司项目经理,是北京Java用户组(BJUG,
http://www.bjug.org)的核心会员,曾在BJUG的讨论会中进行了JMS、Tapestry等主题
演讲,他在JavaEye的ID是"后山",是JavaEye成立之初的老注册会员和JavaEye高级会
员(http://forum.javaeye.com/profile.php?mode=viewprofile&u=33)。一个年轻
人,有感兴趣的工作,不错的前途,还有一群可以随时交流技术的朋友,生活看起来平
淡却充实。

业余时间,王俊经常还利用blog(http://befresh.blogbus.com)写下自己生活和工作
中的酸甜苦辣,此外他还有一个并不富裕但却很温馨的家。

然而从今年二月份起,王俊的blog就再也没有更新过了,他也没有在BJUG的聚会和
javaeye出现了,所有人都以为他出差去了。直到最近,惊闻他要换骨髓,才知道今年
年初,王俊被查出患有“骨髓增生异常综合症”。

骨髓增生异常综合征目前认为是造血干细胞增殖分化异常所致的造血功能障碍。主要表
现为外周血全血细胞减少,骨髓细胞增生,成熟和幼稚细胞有形态异常即病态造血。部
分患者在经历一定时期的MDS后转化成为急性白血病;部分因感染、出血或其他原因死
亡,病程中始终不转化为急性白血病。

这种病目前最有效的治疗手段是换骨髓。万幸的是,王俊的妹妹和他的骨髓配型一致,
免疫系统的疾病发现治疗的越早,就越可能成功,他目前的身体状况还好,只要能更换
骨髓,完全可以康复!但让他们一家望而却步的是,仅手术押金就需要20万,全部疗程
视治疗效果可能需要30-100万。

王俊的家在浙江杭州千岛湖,父母都是农民,已然老迈且没有固定的经济收入,姐姐在
当地出嫁,收入颇低,妹妹目前在北京读成人教育并在公司打工。王俊是家庭经济主要
来源,他的病不仅掐断了家里唯一的经济来源,还要花上对他们而言是天文数字的钱来
治病。

"文章千古事,得失寸心知",这是王俊blog上的座右铭。细细翻看这个典型程序员的
blog,就和他的人一样朴实无华,在那里满眼看到的都是对技术的孜孜追求。谁能想到
一个如此活跃的头脑现在却被病魔折磨着。

生命是美好的,这世界每天都有若干悲剧发生,这次,大家每个人出一份力,这世界就
会少一个悲剧,多一份美好,多一份欢笑。也许,你只是少吃一顿大餐,少买一瓶化妆
品,少看一场演唱会,少买一件名牌服装,少玩一个月的网络游戏,少上一个月的网,
但是你却可以为一个家庭托起一份生的希望。

*****

联系方式 
邮件 help@bjug.org
MSN  icecloud@sina.com 冰云(BJUG) 

援助办法:

1 捐款
帐号:
工商银行
户名 王俊
帐号 0200 2008 0102 3428 807
开户行 工商银行北京市西内所

招商银行
户名 王俊
帐号 9555 5001 0200 2820
开户行 招商银行 北京分行

中国银行
户名 王俊
帐号 4021400-0188-001204-0
开户行 北京西直门支行

国外汇款方式
ADD: BANK OF CHINA BEIJING BRANCH
NO.8 YA BAO LU
BEIJING, CHINA
SWIFT-CODE: BKCHCNBJ110
A/CNo: 4021400-0188-001204-0
NAME: WANG JUN

捐款方式:
A 网上银行
工行请采用行内汇款->有收款帐号汇款
招行请采用个人银行专业版的同城转帐/异地汇款,并选中:采用系统内快速汇款

B 银行汇款
请抄录上述帐号并到银行填写汇款单

请在捐款后,发邮件至help@bjug.org,通知我们,以便统计核对捐款帐目。邮件中请说明以下信息:
 (1) 姓名,
(2) id/网站,
(3) 发出银行/发出帐号,
(4) 金额,
(5) 时间

2 帮助宣传:

  • 请到http://befresh.bjug.org 留下你对他的祝福
  • 请在MSN上修改您的名字,我们都写上 [祝福后山]
  • 请修改您MSN的头像为我们提供的图标
  • 增加行动网站的地址 http://befresh.bjug.org 到MSN名字后面的个人信息
  • 请看到此文的Blogger,在您的blog上link此文,并Trackback到后山的blog
  • 请看到此信息的人,帮助一起宣传,我们需要您的帮助
  • 在您的BLOG或网站,加上用我们提供的LOGO,并连接到网站http://befresh.bjug.org
  • 泡论坛的,请修改你的论坛LOGO和签名档为提供的图标

 

*****

联合发起:
BJUG http://www.bjug.org <http://www.bjug.org/
CSDN http://www.csdn.net <http://www.csdn.net/
JavaEye http://www.javaeye.com <http://www.javaeye.com/
JActionGroup http://www.jactiongroup.net/
Huihoo http://www.huihoo.org <http://www.huihoo.org/
RedSaga http://www.redsaga.com <http://www.redsaga.com/>  
Matrix http://www.matrix.org.cn <http://www.matrix.org.cn/>
Blogbus http://www.blogbus.com <http://www.blogbus.com/

posted @ 2005-07-04 18:48 小米 阅读(1674) | 评论 (22)编辑 收藏
     摘要:       要将BufferedImage实例保存为BMP文件,就需要知道BMP文件的格式,可以参考我转载的文章:《BMP文件格式》。      下面是我的将BufferedImage实例保存为24位色BMP文件的实现。     ...  阅读全文
posted @ 2005-07-04 17:33 小米 阅读(3413) | 评论 (6)编辑 收藏