<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>「理」尚往来</title>
    <description></description>
    <link>http://ssailyang.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Hibernate 的 getCurrentSession 简析</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/215444" style="color:red;">http://ssailyang.javaeye.com/blog/215444</a>&nbsp;
          发表时间: 2008年07月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>SessionFactory.getCurrentSession() 是 Hibernate 应用获取 Session
的常用方法。在调用该方法时，Hibernate 会从 interface CurrentSessionContext 获取当前的
Session，这是Hibernate 在不同组件中传递 Session 的方法。<br id="rx2v" />
<br id="rx2v0" />
CurrentSessionContext 有三个实现，分别是
ThreadLocalSessionContext、JTASessionContext 和
ManagedSessionContext。ThreadLocalSessionContext 将 Session
与当前线程绑定，是使用较多的一种方案；JTASessionContext 将 Session 与 JTA 事务绑定，在 JTA
环境中使用；ManagedSessionContext 使应用可以通过 bind() 和 unbind() 方法控制 Session
的绑定，主要在有 Conversation 的应用中使用（如果使用
ManagedSessionContext，开发人员要做的事情还是很多的）。CurrentSessionContext 实现的选择可以通过
hibernate.current_session_context_class 来配置。<br id="v:ca" />
<br id="v:ca0" />
另一种更常见的创建 Session 的方法是 openSession()。openSession() 与
getCurrentSession() 有何不同和关联呢？在 SessionFactory 启动的时候，Hibernate
会根据配置创建相应的 CurrentSessionContext，在 getCurrentSession() 被调用的时候，实际被执行的方法是
CurrentSessionContext.currentSession() 。在 currentSession() 执行时，如果当前
Session 为空，currentSession 会调用 SessionFactory 的 openSession。所以
getCurrentSession() 对于 Java EE 来说是更好的获取 Session 的方法。<br id="gr:f" />
<br id="gr:f0" />
再说 ManagedSessionContext，它提供了更灵活的绑定 Session 的方式，但是使用起来去不简单。在 Hibernate
的 CaveatEmptor 实例中有关于使用 ManagedSessionContext 的例子，但更好的选择是使用 Seam
Framework。<br id="y31y" />
</p>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/215444#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 16 Jul 2008 15:45:27 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/215444</link>
        <guid>http://ssailyang.javaeye.com/blog/215444</guid>
      </item>
      <item>
        <title>Java EE 应用中的事务</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/202257" style="color:red;">http://ssailyang.javaeye.com/blog/202257</a>&nbsp;
          发表时间: 2008年06月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
    
    
    
    
事务是企业应用开发中的重要概念，对于部分 Web 应用，事务也是非常重要的（试想一下，如果没有事务，ATM 和网银的操作将会使多么的危险）。下面我就对 Java EE 应用中各种事务技术做一个简介。<br id="szik0" />
<br id="hdo_1" />
<span style="font-size: small;"><strong id="zse3">数据库：</strong>
</span>
<br id="lo1z0" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
无论 Java EE 中采用了何种的事务技术，归根结底都是基于数据库的事务。不论是本地事务，还是分布式事务，都必须有数据库的支持才行。各种
Java EE 事务技术也都调用了数据库的事务功能。提到事务，必然要提到事务的四个基本特性：原子性、一致性、隔离性和持久性。Java EE
应用中的各种事务技术直接的或间接的都要保证这四个特性的实现。作为最底层的技术，数据库系统毫无疑问要保证这四个特性被完整的实现。<br id="lo1z1" />
<br id="hdo_2" />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
数据库提供的事务功能是 Java EE
应用中事务的根本。数据库系统一般采用重执行日志保证事务的原子性、一致性和持久性。重执行日志记录了数据库变化的每一个动作，数据库系统会根据重执行日
志，在发生错误的时候撤销已执行的操作；或者在数据库重启时，将尚未持久化的数据重新执行操作。<br id="w82e0" />
<br id="a.yu0" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
对于事务的隔离性，数据库系统采用锁机制来实现，这和 Java
采用的对象锁机制实现线程同步类似，只有持有锁的事务才能操作数据。数据库系统为用户提供了手工操作锁机制的功能，用户在执行 DML 操作和
SELECT FOR UPDATE
时都会获得行锁定，用户也可以进行表锁定。但是手工的操作锁必然是很麻烦的，也容易出现错误，所以数据库系统也提供了自动锁机制，这就引出了数据库的事务
隔离级别。只要用户指定会话的事务隔离级别，数据库就会自动的为事务操作加上适当的锁，并维护这些锁。SQL 92
标准定义了4个等级的事务隔离级别，不同的隔离级别对各种事务并发问题的解决能力是不同的。<br id="kt190" />
<br id="kt191" />
<span style="font-size: small;"><strong id="zse30">JDBC：</strong>
</span>
<br id="gm4q0" />
&nbsp;&nbsp;&nbsp; &nbsp;
JDBC 是大家最为熟悉的技术之一，它是通过数据库系统来实现事务的，所以这里对它的介绍不多。只要调用相应的 API
就可以了，只要了解数据库系统的事务，理解 JDBC 的事务就非常容易了。使用 JDBC
需要数据库的支持，主流的数据库系统都支持单机的事务（相对分布式事务）。当然像一些内存数据库、文件数据库就不好说了。需要说明的是，JDBC
的事务只能在一个 Connection 内实现。<br id="pfv30" />
<br id="pfv31" />
<span style="font-size: small;"><strong id="zse31">JTS 和 JTA：</strong>
</span>
<br id="d7lk" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JTS 规定了 App Server 如何为应用程序提供容器级的事务支持。JTA 规定了 App Server 可以向用户提供哪些 API 用于控制事务。<br id="hl67" />
<br id="hl670" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JTS/JTA 事务与 JDBC 的事务之间对大的不同是前者可以提供跨越多个数据库连接，而后者只能在单个数据库连接中实现事务。所以 JTS/JTA 事务对于企业级应用来说是非常重要的，也导致了大部分开发者对其不是很了解。<br id="ykx:" />
<br id="ykx:0" />
<span style="font-size: small;"><strong id="zse32">Hibernate：</strong>
</span>
<br id="hhtf" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hibernate 是最常用和最流行的 ORM 框架。Hibernate 也提供了基于 JDBC 和 JTA 的事务功能，这也是将 JTS/JTA 事务放在 Hibernate 前面的原因。<br id="qlfx" />
&nbsp;&nbsp;&nbsp;&nbsp; <br id="em6t" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
因为 Hibernate 的事务是基于 JDBC 和 JTA 的，也可以使用容器管理事务，所以很多特性和 JDBC 和 JTA
等并无二异。需要特别提到的是 Hibernate 悲观锁和乐观锁这两个概念。Hibernate
的悲观锁利用的是数据库的行锁机制。使用悲观锁不仅可以保证本应用内的并发事务行，也可以保证使用相同数据库的其它应用不会访问或修改不应该的数据。但
是，悲观锁会影响到应用的并发访问性能。所以，在不是必须使用悲观锁的情况下可以使用乐观锁机制。乐观锁最常见的实现方式是使用 Version
字段，这也是 Hibernate
所推荐的方式。乐观锁可以保证事务和并发性能的兼得，但缺点是事务仅限于同一应用。关于悲观锁和乐观锁的详情很容易在书籍和网络上找到，这里我就不再拗
述。<br id="ws1k" />
<span style="font-size: small;"><br id="ws1k0" />
<strong id="l2.-">Spring：</strong>
</span>

<br id="f:7v" />
&nbsp;&nbsp; &nbsp;&nbsp; Spring 在其它技术的基础上，为开发人员提供了一组统一的易于适用的 API。除了通过编程的方式实现事务外，在 Spring 环境中，也可以使用 XML 或 Annotation 来实现声明式事务。<br id="njfs" />
<br id="njfs0" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlatformTransactionManager 在 Spring
的事务体系中是非常重要的一部分，它是一个抽象接口。HibernateTransactionManager、
JtaTransactionManager 等都实现了这个接口。这些 TransactionManager 的名字都很好理解，我也不多说了。<br id="ad:-" />
<br id="ad:-0" />
&nbsp;&nbsp; &nbsp;&nbsp; Spring 事务最吸引人的特性是声明式事务。Spring 通过 AOP 技术提供了对声明式事务的支持。随着 Spring 版本的更迭，现在使用 Spring 的事务支持已经变得非常容易了。<br id="lkwo" />
<br id="lkwo0" />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: small;"> 除此以外，Spring 还为 JMS 提供了本地事务功能，不过 JMS 的事务和数据库的事务有一定区别，我了解的也不是很多，所以在这里就不再介绍了。</span>
<br id="uyy3" />
<br id="uyy30" />
&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: small;">这篇文章简单总结了一下 Java EE 应用中不同技术所提供的事务支持，写的很粗，欢迎大家补充。打算以后再简要介绍一下 Seam 的事务，如果有必要的话，呵呵。</span>
<br id="hdo_3" />

    
    
</p>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/202257#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 11 Jun 2008 17:55:03 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/202257</link>
        <guid>http://ssailyang.javaeye.com/blog/202257</guid>
      </item>
      <item>
        <title>又开始看《Seam in Action》了</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/201852" style="color:red;">http://ssailyang.javaeye.com/blog/201852</a>&nbsp;
          发表时间: 2008年06月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>没办法，对 Seam 十分感兴趣，而且目前的资料十分有限。对自己的英文有自信而且对 Seam 十分感兴趣的朋友还是可以看 《Seam in Action》的，虽然现在还是草稿。</p>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/201852#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 10 Jun 2008 17:05:47 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/201852</link>
        <guid>http://ssailyang.javaeye.com/blog/201852</guid>
      </item>
      <item>
        <title>看了看《Seam in Action》的 unedited draft</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/201589" style="color:red;">http://ssailyang.javaeye.com/blog/201589</a>&nbsp;
          发表时间: 2008年06月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>刚从网上下了本《Seam in Action》的 unedited draft 看。相信这最终是一本好书，但是现在的 draft 还是不推荐看，有很多语言需要调整。第一章读起来有点费劲。可能是 Seam 的只是不够丰富，所以很多地方看不懂，但是懂得多了也就用不着这本书了。总之，还是等正式版发行吧，再忍忍了。</p>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/201589#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 09 Jun 2008 22:45:22 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/201589</link>
        <guid>http://ssailyang.javaeye.com/blog/201589</guid>
      </item>
      <item>
        <title>EJB 3.0 与 Seam-managed Persistence Context</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/199510" style="color:red;">http://ssailyang.javaeye.com/blog/199510</a>&nbsp;
          发表时间: 2008年06月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>本文将简单谈谈我对 EJB 3.0 的两种 Persistence Context 和 Seam-managed Persistence Context 的不同点的理解、所要解决的问题和我自己所疑惑的问题。<br />
<span style="font-size: medium;"><br />
</span>
<span style="font-size: medium;"><strong>EJB 3.0 (JPA) 的 Persistence Context</strong>
</span>
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    大家在使用 EJB 3.0 的时候会注意到 EJB 3.0 中的容器管理 Persistence Context 有两种类型，一种是 Transaction，另一种是 Extended。这是一个较 Hibernate 的 Session 所没有的概念，Session 没有两种不同的类型，而且最重要的是 Session 不是容器管理的，这里的容器指的是 App Server 容器。这里暂时不谈论 Persistence Context 与 Session 之间的异同，主要谈谈两种 Persistence Context 之间的不同。学过 ORM 的同学都知道，当 Persistence Context 是打开状态的时候，Model 就处于被管理的状态中；当 Persistence Context 关闭之后，Model 就处于了 Detached 状态。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    上面这些特性对于 Transaction 或 Extended 的 Persistence Context 都是一样的，不同的地方在于 Persistence Context 何时被打开关闭。由于绝大多数情况下 Persistence Context 是被容器管理的（如果你不嫌累也可以自己控制 Persistence Context），所以在 EJB 3.0 应用中看不到打开或关闭 Persistence Context 的代码（Spring + Hibernate 的应用也同样如此，Hibernate Session 的管理工作可以交给 Spring 来做）。<br />
<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    其实，Transaction 和 Extended Persistence Context 的不同之处也就在于容器何时打开或关闭 Persistence Context。Transaction 类型的 Persistence Context 的打开和关闭是和事务的打开和关闭是同步的。也就是说在一个事务开始之后，Persistence Context 才会开始；在事务关闭的时候，相应的 Persistence Context 也会被关闭。<br />
    <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    Extended 类型的 Persistence Context 的打开和关闭是和 Stateful Session Bean 的生命周期同步的，是跨越事务的。也就是说，从 SFSB 的初始化开始，直到销毁，Persistence Context 都是存在的。你可以在事务之外执行写操作，但是这是并不会执行真正的数据库操作，写操作只是放入了队列，直到下一个事务，写操作才会真正地被执行。两者的不同简单说来就是 Extended Persistence Context 存在的时间更长。那为什么要有两种不同的 Persistence Context 呢？<br />
<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    当一个 Web 请求到来时，服务器会打开一个线程，这个线程可能会调用一个事务方法，这是一个事务便开始了，当这个请求结束时，线程关闭，事务也随之结束。由于 Transaction 类型的 Persistence Context 的生存周期是在事务范围之内的，所以一个 Web 请求的结束也意味着相应的 Persistence Context 的关闭。由于多数 Web 应用在一次 Web 请求内即可完成一个独立的操作，所以大部分情况下 Transaction 的 Persistence Context 是适用的。但是对于一些复杂的应用，一次操作需要跨越多次请求。这种情况下，如果依旧使用 Transcation 的 Persistence Context，由于每次请求结束后，相应的 Persistence Context 都被关闭，相应的 Model 也就变为 Detached 状态。如果接下来的请求仍然需要这些已经变为 Detached 状态的 Model 就需要重新 load，使用 merge() 方法来持久化。稍有不适就会产生 LazyInitializationException 和 NonUniqueObjectException。同时，这也提高了操作的复杂程度。<br />
<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    如果使用 Extended Persistence Context 就能解决这些问题。由于 Extended Persistence Context 的生命周期是与 SFSB 的生命周期同步的，所以只要多次请求调用的都是同一个 SFSB 中的方法，有多少次的请求，Persistence Context 总是同一个，其中的 Model 也始终是被管理的。很好地解决了 Persistence Context 在线程之间传递的问题，也不会有 LazyInitializationException 和 NonUniqueObjectException 问题的发生。<br />
<span style="font-size: medium;"><br />
</span>
<span style="font-size: medium;"><strong>Seam-managed Persistence Context</strong>
</span>
<br />
<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    EJB 3.0 容器管理之下的 Persistence Context 很不错，能解决很多问题，但是还是有些问题无法解决。Seam 很强大，如果有些问题 EJB 容器解决不了了，没关系，把 Persistence Context 交由 Seam 来管理就 OK 了。那 Seam 都能解决哪些 EJB 不能解决的问题呢？先考虑下面两个问题：</p>
<ol>
<li>
   Extended Persistence Context 虽然可以跨越多个事务，但是每个事务照旧调教不误，这对于想在想让整个操作作为一次事务的话，该如何去做</li>
<li>
   如果一个业务的一组请求只是调用同一个 SFSB 的话，那么 EJB 的 Extended Persistence Context 可以在线程之间传递，使 SFSB 的整个生命周期都使用同一个 Persistence Context。但如果业务需要调用不同的 SFSB 的话，如何在 SFSB 之间传递。</li>
</ol>
<p>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    对于第一个问题，由于 Seam 的 JPA 实现提供者是 Hibernate，而且 Hibernate 提供了一个扩展的 FlushModeType - &quot;Manual&quot;。通过使用这个 FlushModeType，我们可以手工控制何时执行 flush() 操作。在 Seam 的文档中有关于这部分的介绍 《<a href="http://docs.jboss.com/seam/2.0.2.SP1/reference/en-US/html/persistence.html#d0e6706" target="_blank">Seam-managed persistence contexts and atomic conversations</a>
》。文档中使用了一段简单的代码展示 Seam 如何实现所谓的 &quot;atomic conversations&quot;（关于代码的内容我就不介绍了，大家通过我提供的链接来浏览 Seam 的文档）。通过这种方式，事务貌似是跨越了整个事务，但我认为 SFSB 中除了调用 flush() 的方法以外的其它方法不是事务的。其实也没有必要，因为这些方法并没有执行数据库操作，所以没有必要使用事务。当然，如果是乐观事物的话，使用了对性能影响也不大（这只是我的一点浅薄的理解，欢迎指出错误）。只有最后的调用了 flush() 的方法有事务的必要。<br />
    <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    这就引发了一个令我不解的问题。请先看这篇文章《<a href="http://blogs.sun.com/enterprisetechtips/entry/extended_persistence_context_in_stateful" target="_blank">Extended Persistence Context in Stateful Session Beans</a>
》。在这篇文章介绍了如何只使用 EJB 3.0 去解决&ldquo;问题1&rdquo;。文中的 SFSB 的默认事务属性是 &quot;NOT_SUPPORTED&quot;，也就是说这个 SFSB 中的方法默认不是事务的。只有最后的调用 flush() 的方法使用了 &quot;REQUIRED&quot; 的事务属性去覆盖默认设置。也就是最后的方法是事务的，其它的不是。这和 Seam 所做的有区别吗？感觉没有区别。但我认为像 Gavin King 这样的大牛绝不会做无用功的，那问题就是 Seam 实现 &quot;atomic conversations&quot; 的内部细节到底是什么呢？欢迎大家回答这个问题。<br />
<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    对于第二个问题，可以通过使用 Seam-Managed Persistence Context 来解决。Seam-manged Persistence Context 需要在 components.xml 文件中进行配置，并使用 @In 注入到 Seam 的组件中。由于 Seam 是一个比较新的框架技术，所以关于 Seam 是如何使 Persistence Context 在组件中传递并没有详细的介绍。应该只是声明，然后透明地使用即可。在一个 jBPM 流程中被使用到的 Seam 组件，其中的 Persistence Context 应该是可以很容易地被传递。（本不应该使用不确定的和模糊的词语，但无奈现在关于 Seam 的文章资料还是有限，所以我也没有找到关于 Persistence Context 在组件之间调用的例子）<br />
<br />
<strong><span style="font-size: small;">结束语：这篇文章解释的问题不多，不过都是我自己的理解。可能有错误的地方，欢迎大家指出。同时，又有一些新问题产生了，应该可以通过阅读 Seam 提供的例子和源代码得到解释。但 Seam 的例子只看过三个，更多的还没有看。看过的 Seam 的源代码更可以忽略不计。继续努力吧！！</span>
</strong>
<br /></p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/199510#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 02 Jun 2008 18:21:43 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/199510</link>
        <guid>http://ssailyang.javaeye.com/blog/199510</guid>
      </item>
      <item>
        <title>Java Web 的 Security Constraint 配置</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/198578" style="color:red;">http://ssailyang.javaeye.com/blog/198578</a>&nbsp;
          发表时间: 2008年05月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          原来知道 Java Web 应用的 DD 中的 &lt;security-constraint> 配置，但是并没有真正配置过。昨天下午试着配了一下，发现问题还是有一些的。<br /><br />说一下两个需要注意的问题：<br /><ol><li> &lt;security-constraint> 的子元素 &lt;http-method> 是可选的，如果没有 &lt;http-method> 元素，这表示将禁止所有 HTTP 方法访问相应的资源。</li><li> 子元素 &lt;auth-constraint> 需要和 &lt;login-config> 相配合使用，但可以被单独使用。如果没有 &lt;auth-constraint> 子元素，这表明任何身份的用户都可以访问相应的资源。也就是说，如果 &lt;security-constraint> 中没有 &lt;auth-constraint> 子元素的话，配置实际上是不起中用的。如果加入了 &lt;auth-constraint> 子元素，但是其内容为空，这表示所有身份的用户都被禁止访问相应的资源。</li></ol>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/198578#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 30 May 2008 10:58:50 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/198578</link>
        <guid>http://ssailyang.javaeye.com/blog/198578</guid>
      </item>
      <item>
        <title>将 Seam Messages 示例转移到 MySQL 时遇到的问题</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/196410" style="color:red;">http://ssailyang.javaeye.com/blog/196410</a>&nbsp;
          发表时间: 2008年05月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近本人正在将 Seam 中提供的示例重写一遍，以锻炼实际编写 Seam 应用的能力。在将 Seam 提供的 Messages 示例重写的时候遇到了问题。<br /><br />Messages 示例原本使用的是 HSQLDB，在我转移到 MySQL 的时候，程序始终无法正常原因，经过了两天的调试，终于发现了原因。原来 Messages 中的 EntityBean "Message" 有个字段名为 "Read"，在 HSQLDB 下没有问题，但是由于 "Read" 是 MySQL 的保留名，所以在创建表的时候就会有问题。<br /><br />下面这个链接是 MySQL 的保留名词，大家遇到类似问题的时候可以查查，看看是不是使用了保留名。<br /><a href="http://dev.mysql.com/doc/refman/5.0/en/reserved-words.html" target="_blank">My SQL Reserved Words</a>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/196410#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 24 May 2008 18:49:02 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/196410</link>
        <guid>http://ssailyang.javaeye.com/blog/196410</guid>
      </item>
      <item>
        <title>推荐三篇关于 Seam 的文章</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/195383" style="color:red;">http://ssailyang.javaeye.com/blog/195383</a>&nbsp;
          发表时间: 2008年05月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.ibm.com/developerworks/cn/java/j-seam/" target="_blank">Seam - 无缝集成 JSF</a><br /><a href="http://www.javaworld.com/javaworld/jw-04-2008/jw-04-spring-seam.html" target="_blank">Spring into Seam, Part 1: Build a Spring-Seam hybrid component</a><br /><a href="http://www.javaworld.com/javaworld/jw-04-2008/jw-04-spring-seam2.html" target="_blank">Spring into Seam, Part 2: When stateless and stateful collide</a>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/195383#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 21 May 2008 18:10:43 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/195383</link>
        <guid>http://ssailyang.javaeye.com/blog/195383</guid>
      </item>
      <item>
        <title>enum 的那点事</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/192329" style="color:red;">http://ssailyang.javaeye.com/blog/192329</a>&nbsp;
          发表时间: 2008年05月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <ol><li>enum 能够让你摆脱掉大部分的“public static final”变量声明</li><li>通常，你只需要用到 enum 的基本功能</li><li>enum 是 class，所以也可以有方法，也可以实现接口</li><li>enum 如此简单：<pre name="code" class="java">
public enum Grade {
     A, B, C, INCOMPLETE
}
</pre></li>最后不需要分号（某本书上加了分号）<li>从 Java SE 5.0 之后，switch 开始支持 enum</li></ol>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/192329#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 12 May 2008 18:46:13 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/192329</link>
        <guid>http://ssailyang.javaeye.com/blog/192329</guid>
      </item>
      <item>
        <title>[转]ArrayList Vector LinkedList 区别与用法</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/191961" style="color:red;">http://ssailyang.javaeye.com/blog/191961</a>&nbsp;
          发表时间: 2008年05月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.cnblogs.com/mgod/archive/2007/08/05/844011.html" target="_blank">ArrayList Vector LinkedList 区别与用法</a>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/191961#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 11 May 2008 17:45:53 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/191961</link>
        <guid>http://ssailyang.javaeye.com/blog/191961</guid>
      </item>
      <item>
        <title>也谈 EJB 3.1 的新特性</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/175058" style="color:red;">http://ssailyang.javaeye.com/blog/175058</a>&nbsp;
          发表时间: 2008年03月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          看了 kyo100900  翻译的《EJB 3.1 真的来了吗？》之后，我也凑个热闹，谈谈 EJB 3.1 的新特性。<br /><br />   1. 可选的 EJB 接口：<br />      记得刚开始学 EJB 的时候，被 EJB 的接口概念搞得很晕。最不好的是要写一个 Session EJB 就要写一对的接口。在 EJB 3.0 中，我们虽然可以通过 Annotation 简化 EJB 业务接口的声明，但是我们还是免不了要写接口。EJB 3.1 的草案中，我们看到了将 EJB 业务接口改为可选的新特性。我们可以直接将被 @Sessionful 或 @Sessionless 注释的 Bean 作为 Session Bean 来使用。不再需要 implenments 被 @Local 注释的借口了。我没有看 EJB 3.1 草案，但是这个接口简化特性可能只是针对本地业务接口的。也就是说你不用再声明本地接口有哪些方法，Session Bean 中的所有方法都会作为本地接口被暴露出来。毕竟，本地方法相对于远程方法是低资源消耗。但是远程接口又如何呢？我觉得默认情况下，EJB 3.1 中的 Session Bean 的方法是不能被远程访问的，还是需要 Remote Interface 的声明的。但到底如何，还是要看 EJB 3.1 规范正式发布。<br /><br />   2. Singleton Beans：<br />      刚看的这个标题的时候，第一反应是想到了 Spring 中的 Singleton。但实际上，EJB 3.1 的 Singleton 是和 GOF 中的 Singleton 模式是一致的，而不是像 Spring 只是针对 Bean 的 Singleton。Singleton Bean 可以作为一种数据共享方式，并且拥有很多的 Java EE 特性，如事务、线程安全、远程访问等。不过 Singleton Bean 这个新特性到底如何还要看如何使用它。<br /><br />   3. 更简化的封装：<br />      个人感觉简化的封装和原来的封装在不同环境下是各有好处，不过原来的封装形式也不是很麻烦。这个特性的最大吸引人之处在于通过 EJB Lite 可以让 EJB 应用程序运行在 Servlet 容器中。<br /><br />   4. 更强大的 Timer Service：<br />      简单说就是可以用声明的方式创建 Timer 应用了。<br /><br /><br />EJB 3.1 的特性还有很多，但上面是比较重要的。<br /><br />除此以外在谈一下 Web Bean。Web Bean 的目的就是使 JSF 不再需要 Backing Bean（即一般 MVC 框架中 Action 的概念），直接访问 Business Layer。要实现这一点关键是表现层的数据如何传递给业务层。在这个方面，Gavin King 的 Seam 已经做的很好了。Web Bean 的目的是希望 Seam 的一些特性能够进入 Java EE 6 规范中。
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/175058#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 23 Mar 2008 13:13:14 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/175058</link>
        <guid>http://ssailyang.javaeye.com/blog/175058</guid>
      </item>
      <item>
        <title>【总结】使用 Spring 2.5 注释驱动的 IoC 功能</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/172794" style="color:red;">http://ssailyang.javaeye.com/blog/172794</a>&nbsp;
          发表时间: 2008年03月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          原来也看过关于 Spring 2.5 关于注释方面的新特性，但是一直没有一个全面的了解。看完了 IBM developerWorks 上的《<a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/?ca=drs-tp0808" target="_blank">使用 Spring 2.5 注释驱动的 IoC 功能</a>》 后，对这方面的知识有了全面的了解。下面我对这篇文章做一个总结，也是对所学的东西的一个巩固。<br /><br />使用注释驱动 IoC，相对于使用 XML 配置文件的好处是更加简练，对开发人员更加友好，不必在配置文件和代码之间来回切换。但是注释只能用于自己编写的代码，对于第三方类就不能使用了。同时，对于经常会发生变动的配置，也不宜使用注释。<br /><br />使用注释之前，需要在 Spring Context 配置文件中设置对注释的支持。Spring 2.5 提供了 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor 和 RequiredAnnotationBeanPostProcessor 这四个主要的关于 Annotation 的 BeanPostProcessor。我们可以使用 &lt;context:annotation-config /> 来方便地、一次性的声明者四个 BeanPostProcessor。Autowired... 提供对 Spring 特有的 Autowired 和 Qualifier 注释。CommonAnotation... 用于支持 JSR 250 的注释。Persistence... 和 Required... 在本文中没有说明，前者用于 JPA 的 PersistenceUnit 和PersistenceContext 注释；后者用于检查被 Required 注释标记的属性是否被设定。<br /><br />但是用传统的 &lt;bean> 去声明这些 PostProcessor 的做法并不简洁，Spring 2.5 为我们提供了更加简介的方法：&lt;context:annotation-config />。<br /><br />在具体的 Annotation 使用方面，我们可以使用 Spring 2.5 的 @Autowired 来标记我们需要注入的 Bean，它可以应用在 setter 方法或者构造方法上。我们也可以使用 JSR 250 的 @Resource 来实现相同的目的。这两个 Annotation 之间最大的不同在于 @Autowired 是 by-type 的，@Resource 是 by-name 的。在使用 @Autowired 的时候需要主要 Bean 不唯一的情况。<br /><br />JSR 250 还有两个比较重要的 Annotation：@PostConstruct 和 PreDestroy，这里就不多说了。<br /><br />上面提到的 @Autowired 和 @Resource 解决了 Bean 注入的问题，但是还没有为 Bean 的声明提供一条简洁的途径。@Component 实现了这一点。<br /><br />但如果要使用 @Component，我们要在 applicationContext*.xml 里加入 &lt;context:component-scan />，Spring 配置文件的终极简化。
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/172794#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 16 Mar 2008 22:40:35 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/172794</link>
        <guid>http://ssailyang.javaeye.com/blog/172794</guid>
      </item>
      <item>
        <title>Eclipse 中的 Ant 自动运行</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/171398" style="color:red;">http://ssailyang.javaeye.com/blog/171398</a>&nbsp;
          发表时间: 2008年03月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这段时间在学 Seam。Seam 有一个非常方便的代码生成工具 seam-gen。在将用 seam-gen 生成的代码导入 Eclipse 项目之后，我发现每当我保存对源码的修改之后，Eclipse 都会执行 Ant 任务。对于我这种小菜来说，这是非常令人吃惊的现象。<br /><br />研究一番之后，发现其实这样很简单。要实现这样的目的无非需要两个文件：.project 和 *.launch 文件。.project 是 Eclipse 的必备文件，所以必定是位于项目的根目录中；*.launch 一般也位于根目录中。<br /><br />在 seam-gen 生成的 .project 文件中有这么几行代码：<br /><pre name="code" class="xml">
&lt;buildCommand>
    &lt;name>org.eclipse.ui.externaltools.ExternalToolBuilder&lt;/name>
    &lt;triggers>auto,full,incremental,&lt;/triggers>
    &lt;arguments>
        &lt;dictionary>
	    &lt;key>LaunchConfigHandle&lt;/key>
	    &lt;value>&lt;project&gt;/explode.launch&lt;/value>
	&lt;/dictionary>
    &lt;/arguments>
&lt;/buildCommand>
</pre><br /><br />这段代码的意思大致如下：当 anto、full、incremental 触发事件时，explode.launch 所定义的内容会被执行。incremental 应该是当文件增加的意思。auto 和 full 又是什么意思呢？<br /><br />explode.launch 文件中的部分内容：<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
    &lt;stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="clean,unexplode,restart,buildtest,"/>
    &lt;stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
    &lt;stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="clean,unexplode,restart,buildtest,"/>
    &lt;stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="explode,buildtest,"/>
    &lt;stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="seamdemo"/>
    &lt;listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
        &lt;listEntry value="/seamdemo/build.xml"/>
    &lt;/listAttribute>
    &lt;stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/seamdemo/build.xml}"/>
&lt;/launchConfiguration>
</pre><br /><br />当 auto、full、incremental 发生时，<br /><pre name="code" class="xml">
&lt;stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="explode,buildtest,"/>
</pre><br />应该被执行了。explode 和 buildtest 都是 build.xml 中的相应任务。ATTR_ANT_AUTO_TARGETS 从字面上理解也是 Ant 自动任务的意思。<br /><br />对这两个文件内容的理解就到这份上了。再深入时间恐怕不够，暂时也没有需求。<br />希望某位 Eclipse 大拿看到本人后可以给予更详细的解释。<br /><br />问题：<br /><ol><li>auto,full,incremental 的具体含义；</li><li>关于 *.launch 文件的根元素 “launchConfiguration” 的解释；</li><li>。。。。。。</li></ol>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/171398#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 14 Mar 2008 14:26:07 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/171398</link>
        <guid>http://ssailyang.javaeye.com/blog/171398</guid>
      </item>
      <item>
        <title>关于 JPA Annotation 的两点心得</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/166219" style="color:red;">http://ssailyang.javaeye.com/blog/166219</a>&nbsp;
          发表时间: 2008年02月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          第一，注释的继承<br />Class 的属性可以继承，但是注释就不可以了。写一个 Domain 基类，并在其中加入使用了 @Id 和 @GeneratedValue 注释的 id 属性。但在运行时，编译器报告子类缺少 identifier。如果在子类中加入 id 属性（这是需要在基类中去掉 id 属性），这时程序就会运行成功。我在 Spring 的 Samples 中也发现每个 Domain 类都有 id 属性。这样有点浪费代码，但又没有办法。<br /><br />第二，注释的位置<br />注释可以加在属性上，也可以加在 getter 方法上，一般讲这样是可以的。但是还是将所有的注释都加在 getter 方法为好。在我的程序中，如果将 @OneToMany 注释加在属性上就会有异常。具体异常不说了，有兴趣大家可以试试。<br /><br />环境：Spring 2.5，Hibernate 3.2.5，JPA<br /><br />如果大家有不同意见，欢迎回复。
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/166219#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 29 Feb 2008 17:54:34 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/166219</link>
        <guid>http://ssailyang.javaeye.com/blog/166219</guid>
      </item>
      <item>
        <title>值得关注的 Java Content Repository</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/163398" style="color:red;">http://ssailyang.javaeye.com/blog/163398</a>&nbsp;
          发表时间: 2008年02月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="quote_title">引用</div><div class="quote_div">保存各种信息对于应用程序来说非常平常，大多数时候它们是保存在关系数据库中。数据库处理规范数据类型十分在行，但是在处理如图像、文档等二进制数据时却不是那么得心应手。尽管可以用文件系统作为替代——而且它们还提供了更好的性能。但它们既没有提供用于搜索信息的查询语言，也没有提供表示关系或事务的概念。</div><br /><br />上面一段话引用自 infoQ 上的<a href="http://www.infoq.com/cn/articles/spring-modules-jcr" target="_blank">集成Java内容仓库和Spring</a>。其中所表达的需求正式 JCR 所要解决的。似乎在 Java EE 领域 JCR 会有很大的需求。<br /><br />JCR 的某些功能和 JDBC 有些相像，也有事务和锁，毕竟都是为了解决数据存储而出现的，只不过 JCR 要更广义点。<br /><br />现在 Spring Modules 已经有了 JCR 模块了。可能很快就会有更多的 JCR 相关的项目出现。<br /><br />JCR 的出发点很不错，希望能发展起来。JCR，我看行。
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/163398#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 19 Feb 2008 15:43:40 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/163398</link>
        <guid>http://ssailyang.javaeye.com/blog/163398</guid>
      </item>
      <item>
        <title>Introduction To BPM</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/160196" style="color:red;">http://ssailyang.javaeye.com/blog/160196</a>&nbsp;
          发表时间: 2008年01月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>一、一句话介绍</strong><br />BPM 的全称是 Business Process Modeling，也被称为 Business Process Management。这两个名字的含义是一样的。&ldquo;Business Process&rdquo;，业务流程，指的是一个或一系列的，为了实现一个业务目标的，需要一步一步地去完成的算法，而 BPM 指的是设计、执行、管理及监控业务流程的技术和标准。<br /><br />引用 《Essential Business Process Modeling》 中的原话概括一下：“The topic of BPM is profoundly simple to the beginner: the business analyst designs the process, the process is run by an engine, and the engine has EAI and human interaction capabilities.”<br /><br /><br /><strong>二、身世</strong><br />BPM 的前身是工作流技术。工作流（Workflow）就是业务过程的部分或整体在计算机应用环境下的自动化，它主要解决的是使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行，从而实现某个预期的业务目标，或者促使此目标的实现。<br />简单地说，工作流是用来管理和驱动在公司部门内大型人性化和纸制流程的组件。例如，处理一个申请（保险申请），将扫描的纸制申请表格作为输入，电子化地从一个索赔受理者的电子邮箱（或者Work List）传到另一个那里（或者是 Web 表单的传递，但实质是相同的）。这相当于模仿各办公室邮件在办公桌之间传递的传统动作。<br /><br />随着企业业务的不断复杂，要求的不断提高，工作流技术由于本身概念的限制，无法满足这些变化。BPM 便是为了满足这些需求而产生的。可以这么说，BPM 是工作流技术“进化”的结果。<br /><br />更多阅读：<br /><ul><li><a href="http://media.ccidnet.com/art/3021/20070424/1069133_1.html" target="_blank">BPM，一路走来</a></li></ul><br /><br /><strong>三、为什么要使用 BPM</strong><br />对于业务流程的实现，并不是非用 BPM 不可。我们可以用诸如 Java、Python 这样的编程语言实现业务流程，但是 BPM 的优势在于可以灵活稳定地实现业务逻辑。如果不使用 BPM 而使用传统的方法，是很难实现既灵活又稳定的。<br /><br />BPM Suite 可以使用图形化的方式编辑业务逻辑。对于复杂的业务逻辑，这种方法是灵活准确的。这个优点不仅对于开发人员是如此，对于业务人员来说也是如此，因为每个人对于清晰的流程图都是可以很容易理解的。<br /><br />同时，开发人员可以通过流程图生成业务流程引擎能够执行的流程定义语言。而且由于整个过程是在一个框架下执行的，从而在一定程度上保证了流程的稳定性。<br /><br />另一方面，对流程执行状态的持久化是一个不能不考虑的。当然，如果你的服务器能提供足够大的内存，也可以不持久化业务流程的状态。但这可能吗？显然是不可能的。所以，如果你不是用 BPM Suite 所提供的持久化功能，而自己去设计数据库结构，这将是很恐怖的。要记住，你需要设计的系统将要被一个可能是很大的企业适用。<br /><br />所以，综上所述。实现一个业务流程系统理论上并不是非 BPM 不可。但是 BPM 可以让你做的更快更好。可以让你的系统真正投入到实际使用中，而不仅仅是一个实验性的系统。<br /><br /><br /><strong>四、BPM 解决方案概览</strong><br />混乱是 BPM 领域的一个特点。引用 《Essential Business Process Modeling》 一书作者  Mike Havey 的原话便是：“In practice, a <strong>morass（沼泽）</strong> of concepts, terminology, standards, vendors, and philosophies confounds the intermediate-level student of BPM who knows the basics but is lost in detailand is also responsible for building a BPM-based solution. ”<br /><br />如何让大家能够比较清晰的认识一下这个 Morass 呢？我觉得先让大家看图是一个比较好的方法。<br /><br />下图是《Essential Business Process Modeling》这本书的作者 Mike Havey 画的一个 BPMS 架构图。<br /><img src="../../../upload/picture/pic/7330/129e01e6-e5f5-3269-a4e6-206483089c16.png" alt="BPMS " align="middle"" /><br /><br />1. 整个系统的核心是一个流程执行引擎。现在主流的流程定义语言是 BPEL，同样，引擎的主流也是 BPEL 引擎。这里第一次出现 BPEL，所以简单介绍一下。BPEL 的全称是 Web Services Business Process Execution Language。BPEL 是通过编制 Web Services 来实现业务流程定义的，即 BPEL 定义 Web Service 何时、何地和如何被调用。以此来实现某种业务逻辑。<br /> <br />2. 使用 BPEL 定义业务流程，这几乎是绝大多数 BPM 解决方案的实现方法。BPMN，全称为 Business Process Modeling Notation。它的用途是可视化流程定义过程，但它不能被流程执行引擎使用，所以需要将其导出为 BPEL。实际上，BPMN 并不是为 BPEL 而设计的，而是为 BPML ，另一种流程定义语言而设计的。这两种语言是由 BPMI 提出的。所以，很多解决方案并没有使用如图中所示的方案。一些解决方案自己提供了对 BPEL 的可视化编辑方法。<br /> <br />3. BPEL 引擎可以调用内部系统中的 Web Service、Java 代码、C# 代码。对于 BPEL 而言，即便是要调用 Java 或 C# 这样的代码，也需要使用 Web Service 的方式调用。<br /> <br />4. 虽然 BPEL 是用来编制(Orchestration) Web Service 的，但是一个流程也需要和人类交互。既人类对于流程来说不可能只是起点上数据的提供者和终点上数据的消费者，人类也不可避免的会成为流程的参与者。如果要将人类作为流程的参与者，那用户界面别是不可缺少的。所以，商业的 BPM Suite （BPM 解决方案） 都提供了一套完整的功能，用于与人类的交互功能的定义和交互界面的创建。但是这一部分功能并没有统一的规范，虽然 BPEL4People 和 Human-Task 这两个规范已经标准化，但是目前并没有全面采用。这也是 BPM 混乱的一个体现。<br /> <br />5. BPEL 只能使用 Web Service 去调用外部的服务。实际上，调用内部的服务也只能使用 Web Service 的方式。<br /> <br />6. 对 BPMS 的管理和监视。有时，管理员需要知道某个流程的执行情况，这是就需要这个模块了。<br /> <br />7. 每个业务流程实例都是有自己的状态的，而且，流程的执行会持续很长时间，这是就需要流程状态的持久化了。<br /> <br />8. 这部分是比较特殊的。因为我认为在 BPM 领域，WS-CDL 这是多余的（什么是 WS-CDL，什么是 Choreography，这些问题我会在后面解释的）。这里的多余的意思是在大多数 BPM Suite 中，并没有采用 WS-CDL 技术。在这里只要知道你不需要考虑这部分就行了。<br /><br />更多阅读：<br /><ul><li><a href="http://soft.zdnet.com.cn/software_zone/2007/0402/384262.shtml" target="_blank">BPM≠Workflow＋EAI (上)</a></li><li><a href="http://soft.zdnet.com.cn/software_zone/2007/0402/384290.shtml" target="_blank">BPM≠Workflow＋EAI (下)</a></li><li><a href="http://dev2dev.bea.com.cn/techdoc/200701310063.html" target="_blank">面向大众的业务流程管理（BPM）</a></li></ul><br /><br /><br /><strong>五、BPM 的实现</strong><br />这里提供一些关于 BPM 具体实现方法方面的文章。<br /><br />更多阅读：<br /><ul><li><a href="http://www.oracle.com/technology/global/cn/pub/articles/matjaz_bpel1.html" target="_blank">BPEL 实例教程</a></li><li><a href="http://www.eclipse.org/tptp/platform/documents/design/choreography_html/tutorials/wsbpel_tut.html" target="_blank">WS-BPEL 2.0 Tutorial</a></li></ul><br /><br /><br /><strong>六、与 SOA 的联系</strong><br />在如今的企业应用开发领域，BPM 和 SOA 是两个都很火的名词。这一部分是关于两者关系的，但由于这两个技术都是内涵很深，外延很广的，所以这部分只提供一些关于这两个技术的文章，让大家自己阅读。<br /><br />更多阅读：<br /><ul><li><a href="http://dev2dev.bea.com.cn/techdoc/200404186.html" target="_blank">下一代软件架构--SOA</a></li><li><a href="http://soft.zdnet.com.cn/software_zone/2007/0922/518110.shtml" target="_blank">BPM与SOA之间的区别及联系</a></li><li><a href="http://soft.zdnet.com.cn/software_zone/2007/0922/516715.shtml" target="_blank">BPM技术促进SOA发展</a></li><li><a href="http://www.enet.com.cn/article/2007/0315/A20070315485059.shtml" target="_blank">浅谈：SOA实施现状及面临的挑战</a></li></ul><br /><br /><strong>由于本人接触 BPM 时间不长，而且 BPM 也是一个内容颇多的技术，所以本文难免有一些错误、不合理以及应该涉及但没有涉及的地方和内容。欢迎大家对这些问题以及自己对 BPM 的看法踊跃的提出意见。<br /><br />本人在此献丑了。</strong>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/160196#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 29 Jan 2008 18:19:27 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/160196</link>
        <guid>http://ssailyang.javaeye.com/blog/160196</guid>
      </item>
      <item>
        <title>关于 WSDL 样式的两点疑问</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/158134" style="color:red;">http://ssailyang.javaeye.com/blog/158134</a>&nbsp;
          发表时间: 2008年01月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这里的 WSDL 样式指的是 WSDL SOAP 绑定的样式：RPC/Encode、RPC/literal、Document/Encode和Document/literal，以及Document/literal-wrap。<br /><br />对于 WSDL 样式我有两处不解。<br /><br />一、Document/literal 风格的绑定所产生的 SOAP 消息中没有方法名，那它是如何判断它调用的是哪个方法呢？毕竟，WSDL 所定义的 Web Service 是单一 URL 多方法的模式。莫非是根据 soapAction 的定义。但实际上，根据 SOAP标准的定义，soapAction是可有可无的东西。<br /><br />二、RPC样式的缺点在于，由于定义了SOAP客户端和服务器端之间的远程方法调用接口，所以增加了客户端与服务器之间的耦合度。而用 Document/literal-wrap 模拟的RPC实际上也包含有所调用的方法的名字。所以，Document/literal-wrap 也具有RPC的较高的耦合的缺点，而在我看来松耦合是 Document/literal 的最大优点。这么看来 Document/literal-wrap 并不是一个很好的选择。是这样吗？<br /><br />请大家发表一下对这两个问题的看法。
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/158134#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 21 Jan 2008 18:31:35 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/158134</link>
        <guid>http://ssailyang.javaeye.com/blog/158134</guid>
      </item>
      <item>
        <title>学习 Spring 2.5 的新特性，第一部分</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/156159" style="color:red;">http://ssailyang.javaeye.com/blog/156159</a>&nbsp;
          发表时间: 2008年01月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          学习 InfoQ 的《Spring 2.5 的新特性：第一部分》。<a href="http://www.infoq.com/cn/articles/spring-2.5-part-1" target="_blank">原文</a><br /> <br />这篇文章讲的是 Spring 2.5 新加入的 annotation 部分的内容。下面说说我的感受。<br /> <br />这次 Spring 2.5 新加入的 annotation 分为两种，一种是 JSR-250 的公共 annotation，另一种是 Spring 自有 annotation。<br /><br /><strong>JSR-250 Annotation:</strong> 使用这些 Annotation 必须在配置文件里加入一个 Spring post-processor。<br /><ul><li>@Resource: 这个 Annotation 的作用就是提供了用 Annotation 的方式注入资源，不必在 xml 配置文件中显示声明了。还支持根据属性名或属性的类型进行自动的注入。</li><li>@PostConstruct: 这个 Annotation 感觉暂时用不到（对我来说），所以没有细看。有兴趣的可以看原文。</li><li>@PreDestroy: 同上。</li></ul><br /><br /><strong>Spring 2.5 自有的 Annotation</strong>:<br /><ul><li>@Autowired: 这个 Annotation 支持更为灵活的注入。</li><pre name="code" class="java">@Autowired
public void setup(DataSource dataSource, AnotherObject o) { ... } </pre><br />原文这部分说的不是很详细，我的理解是如果 Application 上下文中存在类型是 DataSource 和 AnotherObject 的 Bean 的话，就会自动注入到 setup 方法中。如果是这样的话，@Autowired 是一个很不错的 Annotation，会使你的代码很好很强大，(*^__^*) 嘻嘻……<li>@Qualifier: 也是用于细粒度注入的。</li><li>@Service 和 @Controller: 这个好理解，不多说。反正我感觉这俩是不错东西，做项目的时候在仔细体会吧。</li><li>@Scope: 就是 Spring 2.0 加入的 scope 属性的 Annotation。</li></ul><br /><br />总结：还有一些原文介绍过的 Annotation 没有介绍，主要原因我没大看懂。我觉得这篇文章写的不太好，很多东西介绍的不清楚。想要具体学习 Spring 2.5 的新特性还是看 Spring 提供的例子比较好（我还没有看过，有时间学习下）
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/156159#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 15 Jan 2008 17:30:24 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/156159</link>
        <guid>http://ssailyang.javaeye.com/blog/156159</guid>
      </item>
      <item>
        <title>Introduction to Open Terracotta 段落总结</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/140792" style="color:red;">http://ssailyang.javaeye.com/blog/140792</a>&nbsp;
          发表时间: 2007年11月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal"><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"></span></strong><span style="font-size: 9pt; font-family: 宋体;">最近一段时间我在学习 Terracotta，一种 JVM 级的集群化技术。infoQ 上的&lt;<introduction open="" to="" terracotta="">&gt; 是一篇简要介绍 Terracotta 技术原理和应用的文章，适合大家为了解 Terracotta 而去阅读。为了能更好的理解这篇文章，也希望能够对大家了解 Terracotta 有所帮助，下面我将这篇文章从</introduction></span><strong style=""><span style="font-size: 9pt; font-family: 宋体;"></span></strong><font face="Courier New"> Object Identity and Serialization 开始的部分的每段大意写了出来。写的不好，大家凑合看吧(*^__^*) 嘻嘻&hellip;&hellip;</font></p>
<hr size="2" width="100%" />
<p class="MsoNormal"><strong style=""><span style="font-size: 9pt; font-family: 宋体;">对象识别与序列化</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">不使用</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Java </span><span style="font-size: 9pt; font-family: 宋体;">序列化去复制对象的改变。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">这种方式要比使用</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Java </span><span style="font-size: 9pt; font-family: 宋体;">序列化去复制对象的改变更有效率，因为这种方式仅仅在集群中移动被改变了的数据而不是序列化整个对象图。除了更有效率，这种方式还有另外一个好处：可以保持对象的识别符</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">(ID)</span><span style="font-size: 9pt; font-family: 宋体;">。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span style="font-size: 9pt; font-family: 宋体;">之所以许多其它的集群和缓存技术需要一个</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> GET/PUT API</span><span style="font-size: 9pt; font-family: 宋体;">，是因为如果使用</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Java </span><span style="font-size: 9pt; font-family: 宋体;">序列化在集群中移动改变了的数据，被改变的对象将要被反序列化，并且不得不替换存在了的对象实例。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">没有这种限制。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">(</span><span style="font-size: 9pt; font-family: 宋体;">略</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span style="font-size: 9pt; font-family: 宋体;">在我们的例子中，</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Catalog </span><span style="font-size: 9pt; font-family: 宋体;">中的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Product </span><span style="font-size: 9pt; font-family: 宋体;">对象与</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> shopping cart </span><span style="font-size: 9pt; font-family: 宋体;">中的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Products </span><span style="font-size: 9pt; font-family: 宋体;">是堆中的相同对象。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal"><strong style=""><span style="font-size: 9pt; font-family: 宋体;">虚拟堆</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;">/</span></strong><strong style=""><span style="font-size: 9pt; font-family: 宋体;">网络附加存储</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">可以让我们有效率地使用有很大的对象图的本地</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> JVM </span><span style="font-size: 9pt; font-family: 宋体;">堆。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">会根据实例的使用模式去裁剪共享的对象图的本地实例。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">在集群对象图上维持一个可配置的窗口，不适应一定比例的堆的片段将根据一个缓存策略被清除。当需要那些丢失的片段的时候，它们将会重新从服务器中被载入</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">(fault into?)</span><span style="font-size: 9pt; font-family: 宋体;">。你可以将</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">集群看作是任意大的虚拟堆或</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">network-attached memory</span><span style="font-size: 9pt; font-family: 宋体;">。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span style="font-size: 9pt; font-family: 宋体;">这个特性将允许任意大的对象图</span><span style="font-size: 9pt; font-family: 宋体;">&ldquo;</span><span style="font-size: 9pt; font-family: 宋体;">载入</span><span style="font-size: 9pt; font-family: 宋体;">&rdquo;</span><span style="font-size: 9pt; font-family: 宋体;">标准大小的堆中。在我们的例子中，如果</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Catalog </span><span style="font-size: 9pt; font-family: 宋体;">的数据量变得很大，在没有</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">的情况下，我们将投入大量的硬件资源去保持高可用性和高扩展性。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">(</span><span style="font-size: 9pt; font-family: 宋体;">略</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p> </o:p></span></p>
<p class="MsoNormal"><strong style=""><span style="font-family: 宋体;">你怎样和什么时候使用</span></strong><strong style=""><span new="" courier="" lang="EN-US" style=""> Terracotta</span></strong><strong style=""><span style="font-family: 宋体;">？</span></strong><strong style=""><span new="" courier="" lang="EN-US" style=""><o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">下面列出的是四个有效使用</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">的用例：</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<!--[if !supportLists]-->
<ul>
    <li><span new="" courier="" lang="EN-US" style="font-size: 9pt;">HTTP Session </span><span style="font-size: 9pt; font-family: 宋体;">复制</span></li>
    <li><span style="font-size: 9pt; font-family: 宋体;">分布式缓存</span></li>
    <li><span lang="EN-US" style="font-size: 9pt; font-family: Wingdings;"><span style=""><span font-style:="" new="" font-stretch:="" font-size:="" line-height:="" font-weight:="" times="" font-size-adjust:="" roman="" font-variant:="" style=""></span></span><!--[endif]--><span new="" courier="" lang="EN-US" style="font-size: 9pt;">POJO </span><span style="font-size: 9pt; font-family: 宋体;">集群</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></span></li>
    <li><span style="font-size: 9pt; font-family: 宋体;">协作、协调和事件</span><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"></span></strong></li>
</ul>
<strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;">HTTP Session </span></strong><strong style=""><span style="font-size: 9pt; font-family: 宋体;">复制</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong> <!--[if !supportLists]--><!--[if !supportLists]--><!--[if !supportLists]-->
<p class="MsoNormal" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">在一个多服务器环境中进行</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> HTTP Session </span><span style="font-size: 9pt; font-family: 宋体;">复制可能是最熟悉不过的用例了。现在应用程序的设计趋势是诸如购物车这样的应用程序状态信息存储在一个例如数据库的外部系统（注：放在关系型数据库中对应用程序的性能是有影响的，更好的做法是放在一个公共服务器的内存中），这被称作&ldquo;无状态&rdquo;应用程序设计。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">这种&ldquo;无状态&rdquo;的方法并不是真的无状态。这种方法带来了两种负面影响，第一是对性能的影响，第二是对程序结构的影响。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">的</span><span new="" courier="" style="font-size: 9pt;"> <span lang="EN-US">Session </span></span><span style="font-size: 9pt; font-family: 宋体;">复制允许应用程序的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">数据保持原有的位置和形式，从而使网络应用程序的软件架构依旧简单。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta Session </span><span style="font-size: 9pt; font-family: 宋体;">复制通过允许任何应用程序去访问任何活动的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">来提供高可用性，无论那个</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">是在哪里被创建的。它的扩展性很好，因为只有那些在</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">中被改变了的数据会被复制，并且仅发送到需要它们的地方。如果没有其它的应用程序服务器在堆中拥有这个</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session</span><span style="font-size: 9pt; font-family: 宋体;">，那么将没有其它的服务器会被发送这些修改。只有当服务器失败事件发生时，</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Session </span><span style="font-size: 9pt; font-family: 宋体;">数据才会被复制到其它应用程序服务器，并且仅发生在要求的时候。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">有了</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Terracotta</span><span style="font-size: 9pt; font-family: 宋体;">，你只需像在单个</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> JVM </span><span style="font-size: 9pt; font-family: 宋体;">环境中去使用</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">即可，</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">会很好的完成其它事情。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">在集群运行的时候，你能够看到整个集群中所有的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">的内容。在开发的时候，这被用来发现对</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session </span><span style="font-size: 9pt; font-family: 宋体;">的不恰当使用。在产品使用阶段，你能够立即观察到有多少活动的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Session</span><span style="font-size: 9pt; font-family: 宋体;">，并且看到它们实时的变化。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">可以和很多流行的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Web </span><span style="font-size: 9pt; font-family: 宋体;">框架工作，诸如</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Struts</span><span style="font-size: 9pt; font-family: 宋体;">、</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Spring Web Flow </span><span style="font-size: 9pt; font-family: 宋体;">和</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Wicket</span><span style="font-size: 9pt; font-family: 宋体;">。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal"><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p> </o:p></span></p>
<p class="MsoNormal"><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;">POJO </span></strong><strong style=""><span style="font-size: 9pt; font-family: 宋体;">和</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring </span></strong><strong style=""><span style="font-size: 9pt; font-family: 宋体;">集群</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">在集群中与</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> POJO </span><span style="font-size: 9pt; font-family: 宋体;">工作就如同是在单个</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> JVM </span><span style="font-size: 9pt; font-family: 宋体;">环境中简单，尤其是当你的应用程序使用了</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring beans</span><span style="font-size: 9pt; font-family: 宋体;">。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta for Spring </span><span style="font-size: 9pt; font-family: 宋体;">通过集群</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring beans</span><span style="font-size: 9pt; font-family: 宋体;">，从而在集群中非侵入式地维护</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring Framework</span><span style="font-size: 9pt; font-family: 宋体;">。你可以像平常那样开发</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> single-JVM </span><span style="font-size: 9pt; font-family: 宋体;">的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring </span><span style="font-size: 9pt; font-family: 宋体;">应用程序，然后定义你想集群哪些</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring Context </span><span style="font-size: 9pt; font-family: 宋体;">和在这些</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Context </span><span style="font-size: 9pt; font-family: 宋体;">下的哪些</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring bean</span><span style="font-size: 9pt; font-family: 宋体;">。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta for Spring </span><span style="font-size: 9pt; font-family: 宋体;">也包含对</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring Web Flow </span><span style="font-size: 9pt; font-family: 宋体;">的支持</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">(continuations?)</span><span style="font-size: 9pt; font-family: 宋体;">。这项特性使构建在</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">集群上的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Spring Web </span><span style="font-size: 9pt; font-family: 宋体;">应用程序能够失败转移会话状态。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal"><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p> </o:p></span></p>
<p class="MsoNormal"><strong style=""><span style="font-size: 9pt; font-family: 宋体;">分布式缓存</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong></p>
<p class="MsoNormal"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">(</span><span style="font-size: 9pt; font-family: 宋体;">略</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">)<o:p></o:p></span></p>
<p class="MsoNormal"><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p> </o:p></span></p>
<p class="MsoNormal"><strong style=""><span style="font-size: 9pt; font-family: 宋体;">协作、协调和事件</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 18pt;"><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">的集群并发的特性使它成为</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> JVM </span><span style="font-size: 9pt; font-family: 宋体;">之间非常理想的信号量。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal"><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><span style="">    </span>Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">可以在集群上实现</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> Master-Worker </span><span style="font-size: 9pt; font-family: 宋体;">模式，从而处理并发事件。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
<p class="MsoNormal"><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p> </o:p></span></p>
<p class="MsoNormal" style="margin-left: 4.5pt; text-indent: -4.5pt;"><strong style=""><span style="font-size: 9pt; font-family: 宋体;">总结</span></strong><strong style=""><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></strong><br />
<span new="" courier="" lang="EN-US" style="font-size: 9pt;">   Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">是一个新型轻量软件栈的基础（什么意思，</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta </span><span style="font-size: 9pt; font-family: 宋体;">规模还要做大？）。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Terracotta</span><span style="font-size: 9pt; font-family: 宋体;">使得开源组件诸如</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Tomcat</span><span style="font-size: 9pt; font-family: 宋体;">、</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Spring</span><span style="font-size: 9pt; font-family: 宋体;">、</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">Geronimo </span><span style="font-size: 9pt; font-family: 宋体;">和开源应用程序框架的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"> host? </span><span style="font-size: 9pt; font-family: 宋体;">可以组装在一起，并且以企业级的可用性和可扩展性被部署的</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;">JVM </span><span style="font-size: 9pt; font-family: 宋体;">级的集群技术可以轻易的被使用。</span><span new="" courier="" lang="EN-US" style="font-size: 9pt;"><o:p></o:p></span></p>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/140792#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 Nov 2007 10:30:20 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/140792</link>
        <guid>http://ssailyang.javaeye.com/blog/140792</guid>
      </item>
      <item>
        <title>将路径硬编码到环境变量中的后果</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/139992" style="color:red;">http://ssailyang.javaeye.com/blog/139992</a>&nbsp;
          发表时间: 2007年11月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          前段时间为了使 IDLE 可以方便地调试 Django 程序，我便将 PYTHONPATH 和 DJANGO_SETTINGS_MODULE 硬编码到了系统的环境变量中了。之后，用 IDLE 调试 Django 程序果然简单了（其实也就用了那么一回，后来也就没有再用 IDLE 调试 Django 程序）。之后，那两个变量也就再没有从环境变量中清除。<br />
后来，由于某些原因我更换了 Django 的工作目录。问题也就随之而来，由于 PYTHONPATH 和 DJANGO_SETTINGS_MODULE 是被硬编码的，所以是不会改变的，导致程序运行时路径出错，花了很长时间才想起来是因为自己硬编码了那两个变量。<br />
所以，大家一定不要图一时之快而去硬编码 Django 运行时需要的变量。（估计只有我才这么做！我的时间呀！！！）
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/139992#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 12 Nov 2007 18:42:27 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/139992</link>
        <guid>http://ssailyang.javaeye.com/blog/139992</guid>
      </item>
      <item>
        <title>常用 Hibernate 方法比较</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/131991" style="color:red;">http://ssailyang.javaeye.com/blog/131991</a>&nbsp;
          发表时间: 2007年10月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font face="Courier New"><strong><font size="2" color="#0000ff">update() 与 merge()</font></strong><br />
update() 与 merge() 的功能是相同的，都是持久化 Detached 状态的对象。但如果当前 Session 中存在两个或两个以上的，持久化标示相同的对象的话，update() 操作是会抛出异常的。而 merge() 会合并你对持久化对象的改动。<br />
除了上面一点 merge() 与 update() 不同外，merge() 可以被看做是 saveOrUpdate()。<br />
<br />
&nbsp;&nbsp;&nbsp; 在 Hibernate 参考文档的 <a href="http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/objectstate.html#objectstate-saveorupdate">第 10 章 与对象共事</a> 中有关于 saveOrUpdate() 与 merge() 不同点的介绍。还有一点不同，merge() 会返回持久化对象实例，而 saveOrUpdate() 没有返回值。<br />
<br />
未完待续...</font>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/131991#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 15 Oct 2007 16:24:45 +0800</pubDate>
        <link>http://ssailyang.javaeye.com/blog/131991</link>
        <guid>http://ssailyang.javaeye.com/blog/131991</guid>
      </item>
      <item>
        <title>常用 JPA Annotation [转]</title>
        <author>SSailYang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ssailyang.javaeye.com">SSailYang</a>&nbsp;
          链接：<a href="http://ssailyang.javaeye.com/blog/131952" style="color:red;">http://ssailyang.javaeye.com/blog/131952</a>&nbsp;
          发表时间: 2007年10月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h2>Table</h2>
<p>Table用来定义entity主表的name，catalog，schema等属性。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name: 表名 </li>
    <li>catalog: 对应关系数据库中的catalog </li>
    <li>schema：对应关系数据库中的schema </li>
    <li>UniqueConstraints:定义一个UniqueConstraint数组，指定需要建唯一约束的列 </li>
</ul>
<div class="source">
<pre>    <br />    @Entity<br />    @Table(name=&quot;CUST&quot;)<br />    public class Customer { ... }<br />　　</pre>
</div>
<div class="section"><a name="SecondaryTable"></a>
<h2>SecondaryTable</h2>
<p>一个entity class可以映射到多表，SecondaryTable用来定义单个从表的名字，主键名字等属性。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name: 表名 </li>
    <li>catalog: 对应关系数据库中的catalog </li>
    <li>schema：对应关系数据库中的schema </li>
    <li>pkJoin: 定义一个PrimaryKeyJoinColumn数组，指定从表的主键列 </li>
    <li>UniqueConstraints:定义一个UniqueConstraint数组，指定需要建唯一约束的列 </li>
</ul>
<p>下面的代码说明Customer类映射到两个表，主表名是CUSTOMER，从表名是CUST_DETAIL，从表的主键列和主表的主键列类型相同，列名为CUST_ID。</p>
<div class="source">
<pre>                <br />    @Entity<br />    @Table(name=&quot;CUSTOMER&quot;)<br />	@SecondaryTable(name=&quot;CUST_DETAIL&quot;,pkJoin=@PrimaryKeyJoinColumn(name=&quot;CUST_ID&quot;))<br />	public class Customer { ... }<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="SecondaryTables"></a>
<h2>SecondaryTables</h2>
<p>当一个entity class映射到一个主表和多个从表时，用SecondaryTables来定义各个从表的属性。</p>
<p>元数据属性说明：</p>
<ul>
    <li>value： 定义一个SecondaryTable数组，指定每个从表的属性。 </li>
</ul>
<div class="source">
<pre>                <br />	@Table(name = &quot;CUSTOMER&quot;)<br />	@SecondaryTables( value = {<br />	@SecondaryTable(name = &quot;CUST_NAME&quot;, pkJoin = { @PrimaryKeyJoinColumn(name = &quot;STMO_ID&quot;, referencedColumnName = &quot;id&quot;) }),<br />	@SecondaryTable(name = &quot;CUST_ADDRESS&quot;, pkJoin = { @PrimaryKeyJoinColumn(name = &quot;STMO_ID&quot;, referencedColumnName = &quot;id&quot;) }) })<br />	public class Customer {}<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="UniqueConstraint"></a>
<h2>UniqueConstraint</h2>
<p>UniqueConstraint定义在Table或SecondaryTable元数据里，用来指定建表时需要建唯一约束的列。</p>
<p>元数据属性说明：</p>
<ul>
    <li>columnNames:定义一个字符串数组，指定要建唯一约束的列名。 </li>
</ul>
<div class="source">
<pre>                <br />		@Entity<br />		@Table(name=&quot;EMPLOYEE&quot;,<br />			uniqueConstraints={@UniqueConstraint(columnNames={&quot;EMP_ID&quot;, &quot;EMP_NAME&quot;})}<br />		)<br />		public class Employee { ... }<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="Column"></a>
<h2>Column</h2>
<p>Column元数据定义了映射到数据库的列的所有属性：列名，是否唯一，是否允许为空，是否允许更新等。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name:列名。 </li>
    <li>unique: 是否唯一 </li>
    <li>nullable: 是否允许为空 </li>
    <li>insertable: 是否允许插入 </li>
    <li>updatable: 是否允许更新 </li>
    <li>columnDefinition: 定义建表时创建此列的DDL </li>
    <li>secondaryTable: 从表名。如果此列不建在主表上（默认建在主表），该属性定义该列所在从表的名字。 </li>
</ul>
<div class="source">
<pre>        <br />    public class Person {<br />	@Column(name = &quot;PERSONNAME&quot;, unique = true, nullable = false, updatable = true)<br />	private String name;<br /><br />	@Column(name = &quot;PHOTO&quot;, columnDefinition = &quot;BLOB NOT NULL&quot;, secondaryTable=&quot;PER_PHOTO&quot;)<br />	private byte[] picture;<br />		<br />    </pre>
</div>
</div>
<div class="section"><a name="JoinColumn"></a>
<h2>JoinColumn</h2>
<p>如果在entity class的field上定义了关系（one2one或one2many等），我们通过JoinColumn来定义关系的属性。JoinColumn的大部分属性和Column类似。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name:列名。 </li>
    <li>referencedColumnName:该列指向列的列名（建表时该列作为外键列指向关系另一端的指定列） </li>
    <li>unique: 是否唯一 </li>
    <li>nullable: 是否允许为空 </li>
    <li>insertable: 是否允许插入 </li>
    <li>updatable: 是否允许更新 </li>
    <li>columnDefinition: 定义建表时创建此列的DDL </li>
    <li>secondaryTable: 从表名。如果此列不建在主表上（默认建在主表），该属性定义该列所在从表的名字。 </li>
</ul>
<p>下面的代码说明Custom和Order是一对一关系。在Order对应的映射表建一个名为CUST_ID的列，该列作为外键指向Custom对应表中名为ID的列。</p>
<div class="source">
<pre>                <br />	public class Custom {<br />	<br />    @OneToOne<br />	@JoinColumn(<br />	name=&quot;CUST_ID&quot;, referencedColumnName=&quot;ID&quot;, unique=true, nullable=true, updatable=true)<br />	public Order getOrder() {<br />		return order;<br />	}<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="JoinColumns"></a>
<h2>JoinColumns</h2>
<p>如果在entity class的field上定义了关系（one2one或one2many等），并且关系存在多个JoinColumn，用JoinColumns定义多个JoinColumn的属性。</p>
<p>元数据属性说明：</p>
<ul>
    <li>value: 定义JoinColumn数组，指定每个JoinColumn的属性。 </li>
</ul>
<p>下面的代码说明Custom和Order是一对一关系。在Order对应的映射表建两列，一列名为CUST_ID，该列作为外键指向Custom对应表中名为ID的列,另一列名为CUST_NAME，该列作为外键指向Custom对应表中名为NAME的列。</p>
<div class="source">
<pre>                <br />	public class Custom {<br />    @OneToOne<br />	@JoinColumns({<br />    @JoinColumn(name=&quot;CUST_ID&quot;, referencedColumnName=&quot;ID&quot;),<br />    @JoinColumn(name=&quot;CUST_NAME&quot;, referencedColumnName=&quot;NAME&quot;)<br />	})<br />	public Order getOrder() {<br />		return order;<br />	}<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="Id"></a>
<h2>Id</h2>
<p>声明当前field为映射表中的主键列。id值的获取方式有五种：TABLE, SEQUENCE, IDENTITY, AUTO, NONE。Oracle和DB2支持SEQUENCE，SQL Server和Sybase支持IDENTITY,mysql支持AUTO。所有的数据库都可以指定为AUTO，我们会根据不同数据库做转换。NONE (默认)需要用户自己指定Id的值。元数据属性说明：</p>
<ul>
    <li>generate():主键值的获取类型 </li>
    <li>generator():TableGenerator的名字（当generate=GeneratorType.TABLE才需要指定该属性） </li>
</ul>
<p>下面的代码声明Task的主键列id是自动增长的。(Oracle和DB2从默认的SEQUENCE取值，SQL Server和Sybase该列建成IDENTITY，mysql该列建成auto increment。)</p>
<div class="source">
<pre>                <br />    @Entity<br />    @Table(name = &quot;OTASK&quot;)<br />    public class Task {<br />	  @Id(generate = GeneratorType.AUTO)<br />	  public Integer getId() {<br />		  return id;<br />	  }<br />    }<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="IdClass"></a>
<h2>IdClass</h2>
<p>当entity class使用复合主键时，需要定义一个类作为id class。id class必须符合以下要求:类必须声明为public，并提供一个声明为public的空构造函数。必须实现Serializable接，覆写 equals()和hashCode（）方法。entity class的所有id field在id class都要定义，且类型一样。</p>
<p>元数据属性说明：</p>
<ul>
    <li>value: id class的类名 </li>
</ul>
<p>&nbsp;</p>
<div class="source">
<pre>                <br />    public class EmployeePK implements java.io.Serializable{<br />       String empName;<br />       Integer empAge;<br /><br />	   public EmployeePK(){}<br /><br />	   public boolean equals(Object obj){ ......}<br />	   public int hashCode(){......}<br />    }<br /><br /><br />    @IdClass(value=com.acme.EmployeePK.class)<br />    @Entity(access=FIELD)<br />    public class Employee {<br />        @Id String empName;<br />        @Id Integer empAge;<br />    }<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="MapKey"></a>
<h2>MapKey</h2>
<p>在一对多，多对多关系中，我们可以用Map来保存集合对象。默认用主键值做key，如果使用复合主键，则用id class的实例做key，如果指定了name属性，就用指定的field的值做key。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name: 用来做key的field名字 </li>
</ul>
<p>下面的代码说明Person和Book之间是一对多关系。Person的books字段是Map类型，用Book的isbn字段的值作为Map的key。</p>
<div class="source">
<pre>                <br />    @Table(name = &quot;PERSON&quot;)<br />    public class Person {<br /><br />	@OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = &quot;person&quot;)<br />	@MapKey(name = &quot;isbn&quot;)<br />	private Map<string> books = new HashMap<string>();<br />    }<br />    <br />    </string></string></pre>
</div>
</div>
<div class="section"><a name="OrderBy"></a>
<h2>OrderBy</h2>
<p>在一对多，多对多关系中，有时我们希望从数据库加载出来的集合对象是按一定方式排序的，这可以通过OrderBy来实现，默认是按对象的主键升序排列。</p>
<p>元数据属性说明：</p>
<ul>
    <li>value: 字符串类型，指定排序方式。格式为&quot;fieldName1 [ASC|DESC],fieldName2 [ASC|DESC],......&quot;,排序类型可以不指定，默认是ASC。 </li>
</ul>
<p>下面的代码说明Person和Book之间是一对多关系。集合books按照Book的isbn升序，name降序排列。</p>
<div class="source">
<pre>                <br />    @Table(name = &quot;MAPKEY_PERSON&quot;)<br />    public class Person {<br /><br />	@OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedBy = &quot;person&quot;)<br />	@OrderBy(name = &quot;isbn ASC, name DESC&quot;)<br />	private List<book> books = new ArrayList<book>();<br />    }<br />    <br />    </book></book></pre>
</div>
</div>
<div class="section"><a name="PrimaryKeyJoinColumn"></a>
<h2>PrimaryKeyJoinColumn</h2>
<p>在三种情况下会用到PrimaryKeyJoinColumn。 </p>
<ul>
    <li>继承。 </li>
    <li>entity class映射到一个或多个从表。从表根据主表的主键列（列名为referencedColumnName值的列），建立一个类型一样的主键列，列名由name属性定义。 </li>
    <li>one2one关系，关系维护端的主键作为外键指向关系被维护端的主键，不再新建一个外键列。 </li>
</ul>
<p>&nbsp;</p>
<p>元数据属性说明：</p>
<ul>
    <li>name:列名。 </li>
    <li>referencedColumnName:该列引用列的列名 </li>
    <li>columnDefinition: 定义建表时创建此列的DDL </li>
</ul>
<p>下面的代码说明Customer映射到两个表，主表CUSTOMER,从表CUST_DETAIL，从表需要建立主键列CUST_ID，该列和主表的主键列id除了列名不同，其他定义一样。 </p>
<div class="source">
<pre>            <br />    @Entity<br />    @Table(name=&quot;CUSTOMER&quot;)<br />	@SecondaryTable(name=&quot;CUST_DETAIL&quot;,pkJoin=@PrimaryKeyJoinColumn(name=&quot;CUST_ID&quot;，referencedColumnName=&quot;id&quot;))<br />	public class Customer { <br />	 @Id(generate = GeneratorType.AUTO)<br />	  public Integer getId() {<br />		  return id;<br />	  }<br />	}<br />    <br />    </pre>
</div>
<p>下面的代码说明Employee和EmployeeInfo是一对一关系，Employee的主键列id作为外键指向EmployeeInfo的主键列INFO_ID。 </p>
<div class="source">
<pre>            <br />    @Table(name = &quot;Employee&quot;)<br />    public class Employee {<br />	@OneToOne<br />	@PrimaryKeyJoinColumn(name = &quot;id&quot;, referencedColumnName=&quot;INFO_ID&quot;)<br />	EmployeeInfo info;<br />	}<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="PrimaryKeyJoinColumns"></a>
<h2>PrimaryKeyJoinColumns</h2>
<p>如果entity class使用了复合主键，指定单个PrimaryKeyJoinColumn不能满足要求时，可以用PrimaryKeyJoinColumns来定义多个PrimaryKeyJoinColumn。 </p>
<p>元数据属性说明：</p>
<ul>
    <li>value: 一个PrimaryKeyJoinColumn数组，包含所有PrimaryKeyJoinColumn。 </li>
</ul>
<p>下面的代码说明了Employee和EmployeeInfo是一对一关系。他们都使用复合主键，建表时需要在Employee表建立一个外键，从Employee的主键列id,name指向EmployeeInfo的主键列INFO_ID和INFO_NAME. </p>
<div class="source">
<pre>            <br />   @Entity<br />   @IdClass(EmpPK.class)<br />   @Table(name = &quot;EMPLOYEE&quot;)<br />   public class Employee {<br /><br />	private int id;<br /><br />	private String name;<br /><br />	private String address;<br /><br />	@OneToOne(cascade = CascadeType.ALL)<br />	@PrimaryKeyJoinColumns({<br />	@PrimaryKeyJoinColumn(name=&quot;id&quot;, referencedColumnName=&quot;INFO_ID&quot;),<br />	@PrimaryKeyJoinColumn(name=&quot;name&quot; , referencedColumnName=&quot;INFO_NAME&quot;)})<br />	EmployeeInfo info;<br />    }<br /><br />    @Entity<br />    @IdClass(EmpPK.class)<br />    @Table(name = &quot;EMPLOYEE_INFO&quot;)<br />    public class EmployeeInfo {<br /><br />	@Id<br />	@Column(name = &quot;INFO_ID&quot;)<br />	private int id;<br /><br />	@Id<br />	@Column(name = &quot;INFO_NAME&quot;)<br />	private String name;<br />	}<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="Transient"></a>
<h2>Transient</h2>
<p>Transient用来注释entity的属性，指定的这些属性不会被持久化，也不会为这些属性建表。</p>
<div class="source">
<pre>    <br />    @Transient<br />    private String name;<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="Version"></a>
<h2>Version</h2>
<p>Version指定实体类在乐观事务中的version属性。在实体类重新由EntityManager管理并且加入到乐观事务中时，保证完整性。每一个类只能有一个属性被指定为version，version属性应该映射到实体类的主表上。</p>
<p>下面的代码说明versionNum属性作为这个类的version，映射到数据库中主表的列名是OPTLOCK。</p>
<div class="source">
<pre>                <br />    @Version<br />    @Column(&quot;OPTLOCK&quot;)<br />    protected int getVersionNum() { return versionNum; }<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="Lob"></a>
<h2>Lob</h2>
<p>Lob指定一个属性作为数据库支持的大对象类型在数据库中存储。使用LobType这个枚举来定义Lob是二进制类型还是字符类型。</p>
<p>LobType枚举类型说明：</p>
<ul>
    <li>BLOB 二进制大对象，Byte[]或者Serializable的类型可以指定为BLOB。 </li>
    <li>CLOB 字符型大对象，char[]、Character[]或String类型可以指定为CLOB。 </li>
</ul>
<p>元数据属性说明：</p>
<ul>
    <li>fetch： 定义这个字段是lazy loaded还是eagerly fetched。数据类型是FetchType枚举，默认为LAZY,即lazy loaded. </li>
    <li>type： 定义这个字段在数据库中的JDBC数据类型。数据类型是LobType枚举，默认为BLOB。 </li>
</ul>
<p>下面的代码定义了一个BLOB类型的属性和一个CLOB类型的属性。</p>
<div class="source">
<pre>                <br />    @Lob<br />    @Column(name=&quot;PHOTO&quot; columnDefinition=&quot;BLOB NOT NULL&quot;)<br />    protected JPEGImage picture;<br />    <br />    @Lob(fetch=EAGER, type=CLOB)<br />    @Column(name=&quot;REPORT&quot;)<br />    protected String report;<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="JoinTable"></a>
<h2>JoinTable</h2>
<p>JoinTable在many-to-many关系的所有者一边定义。如果没有定义JoinTable，使用JoinTable的默认值。</p>
<p>元数据属性说明：</p>
<ul>
    <li>table:这个join table的Table定义。 </li>
    <li>joinColumns:定义指向所有者主表的外键列，数据类型是JoinColumn数组。 </li>
    <li>inverseJoinColumns:定义指向非所有者主表的外键列，数据类型是JoinColumn数组。 </li>
</ul>
<p>下面的代码定义了一个连接表CUST和PHONE的join table。join table的表名是CUST_PHONE，包含两个外键，一个外键是CUST_ID，指向表CUST的主键ID，另一个外键是PHONE_ID，指向表PHONE的主键ID。</p>
<div class="source">
<pre>                <br />    @JoinTable(<br />    table=@Table(name=CUST_PHONE),<br />    joinColumns=@JoinColumn(name=&quot;CUST_ID&quot;, referencedColumnName=&quot;ID&quot;),<br />    inverseJoinColumns=@JoinColumn(name=&quot;PHONE_ID&quot;, referencedColumnName=&quot;ID&quot;)<br />    )<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="TableGenerator"></a>
<h2>TableGenerator</h2>
<p>TableGenerator定义一个主键值生成器，在Id这个元数据的generate＝TABLE时，generator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义。</p>
<p>生成器是为多个实体类提供连续的ID值的表，每一行为一个类提供ID值，ID值通常是整数。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name:生成器的唯一名字，可以被Id元数据使用。 </li>
    <li>table:生成器用来存储id值的Table定义。 </li>
    <li>pkColumnName:生成器表的主键名称。 </li>
    <li>valueColumnName:生成器表的ID值的列名称。 </li>
    <li>pkColumnValue:生成器表中的一行数据的主键值。 </li>
    <li>initialValue:id值的初始值。 </li>
    <li>allocationSize:id值的增量。 </li>
</ul>
<p>下面的代码定义了两个生成器empGen和addressGen，生成器的表是ID_GEN。</p>
<div class="source">
<pre>                <br />    @Entity public class Employee {<br />    ...<br />    @TableGenerator(name=&quot;empGen&quot;,<br />    table=@Table(name=&quot;ID_GEN&quot;),<br />    pkColumnName=&quot;GEN_KEY&quot;,<br />    valueColumnName=&quot;GEN_VALUE&quot;,<br />    pkColumnValue=&quot;EMP_ID&quot;,<br />    allocationSize=1)<br />    @Id(generate=TABLE, generator=&quot;empGen&quot;)<br />    public int id;<br />    ...<br />    }<br />    <br />    @Entity public class Address {<br />    ...<br />    @TableGenerator(name=&quot;addressGen&quot;,<br />    table=@Table(name=&quot;ID_GEN&quot;),<br />    pkColumnValue=&quot;ADDR_ID&quot;)<br />    @Id(generate=TABLE, generator=&quot;addressGen&quot;)<br />    public int id;<br />    ...<br />    }<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="SequenceGenerator"></a>
<h2>SequenceGenerator</h2>
<p>SequenceGenerator定义一个主键值生成器，在Id这个元数据的generator属性中可以使用生成器的名字。生成器可以在类、方法或者属性上定义。生成器是数据库支持的sequence对象。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name:生成器的唯一名字，可以被Id元数据使用。 </li>
    <li>sequenceName:数据库中，sequence对象的名称。如果不指定，会使用提供商指定的默认名称。 </li>
    <li>initialValue:id值的初始值。 </li>
    <li>allocationSize:id值的增量。 </li>
</ul>
<p>下面的代码定义了一个使用提供商默认名称的sequence生成器。</p>
<div class="source">
<pre>                <br />    @SequenceGenerator(name=&quot;EMP_SEQ&quot;, allocationSize=25)	<br />    <br />    </pre>
</div>
</div>
<div class="section"><a name="DiscriminatorColumn"></a>
<h2>DiscriminatorColumn</h2>
<p>DiscriminatorColumn定义在使用SINGLE_TABLE或JOINED继承策略的表中区别不继承层次的列。</p>
<p>元数据属性说明：</p>
<ul>
    <li>name:column的名字。默认值为TYPE。 </li>
    <li>columnDefinition:生成DDL的sql片断。 </li>
    <li>length:String类型的column的长度，其他类型使用默认值10。 </li>
</ul>
<p>下面的代码定义了一个列名为DISC，长度为20的String类型的区别列。</p>
<div class="source">
<pre>                <br />    @Entity<br />    @Table(name=&quot;CUST&quot;)<br />    @Inheritance(strategy=SINGLE_TABLE,<br />        discriminatorType=STRING,<br />       discriminatorValue=&quot;CUSTOMER&quot;)<br />    @DiscriminatorColumn(name=&quot;DISC&quot;, length=20)<br />    public class Customer { ... }<br />    <br />    </pre>
</div>
</div>
          <br/>
          <span style="color:red;">
            <a href="http://ssailyang.javaeye.com/blog/131952#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 15 Oct 2007 14:15:43 +0800