<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Java论坛最新讨论 - JavaEye</title>
    <description>Java编程、Java Web开发、Java企业应用、Java设计模式、Java开源框架、Java应用服务器 <br/>
圈子: 
<a href="http://android.group.javaeye.com/" target="_blank">Android</a>
<a href="http://jbpm.group.javaeye.com/" target="_blank">JBPM</a>
<a href="http://jsfgroup.group.javaeye.com/" target="_blank">JSF</a>
<a href="http://seam.group.javaeye.com/" target="_blank">Seam</a>
<a href="http://tapestrying.group.javaeye.com/" target="_blank">Tapestry</a>
<a href="http://grails.group.javaeye.com" target="_blank">Groovy</a>
<a href="http://lucene-group.group.javaeye.com/" target="_blank">Lucene</a>
<a href="http://ecside.group.javaeye.com/" target="_blank">GT-Grid</a>

 - Java编程，Ruby编程，微软.net，AJAX，敏捷软件开发，综合软件技术</description>
    <link>http://www.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>java 读取linux下的硬盘序列号问题</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://paradise2009.javaeye.com">paradise2009</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/232444" style="color:red;">http://www.javaeye.com/topic/232444</a>&nbsp;
          发表时间: 2008年08月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          想通过java写一个读取安装在linux系统上的硬盘的序列号的util类。<br /><br />我写的代码是：<br /><br /><pre name="code" class="java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * 
 * Description: 获取各个操作系统下硬盘序列号
 * 
 * 
 * @version 1.0 Aug 25, 2008 12:12:36 PM
 *       
 */

public class HDUtil {

	/**
	 * Return Opertaion System Name;
	 * 
	 * @return os name.
	 */
	public static String getOsName() {
		String os = "";
		os = System.getProperty("os.name");
		return os;
	}

	/**
	 * Returns the HD SerialNo. of the computer.
	 * 
	 * @return the HD SerialNo.
	 */
	public static String getHDSerialNo() {
		String sn = "";
		String os = getOsName();
		if (os.startsWith("Linux")) {
			if (isSCSIorIDEHD() == "scsi") {
				// 注意如果是ubuntu等系统用户，本身没有root权限，请先：chmod 777 /dev/sda
				String command = "hdparm -i /dev/sda";
				Process p;
				try {
					p = Runtime.getRuntime().exec(command);
					BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
					String line;
					while ((line = br.readLine()) != null) {
						if (line.contains("SerialNo")) {
							int index = line.indexOf("SerialNo") + "SerialNo".length() + 1;
							sn = line.substring(index);
							break;
						}
					}
					br.close();
				} catch (IOException e) {
				}
			} else if (isSCSIorIDEHD() == "ide") {
				// 注意如果是ubuntu等系统用户，本身没有root权限，请先：chmod 777 /dev/sda
				String command = "hdparm -i /dev/hda";
				Process p;
				try {
					p = Runtime.getRuntime().exec(command);
					BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
					String line;
					while ((line = br.readLine()) != null) {
						if (line.contains("SerialNo")) {
							int index = line.indexOf("SerialNo") + "SerialNo".length() + 1;
							sn = line.substring(index);
							break;
						}
					}
					br.close();
				} catch (IOException e) {
				}
			} else {
				sn = "unknown";
			}

		}
		sn = sn.trim();
		return sn;
	}

	public static String isSCSIorIDEHD() {
		String os = getOsName();
		if (os.startsWith("Linux")) {
			// ubuntu系统下确定有root权限
			String command = "fdisk -l";
			Process p;
			try {
				p = Runtime.getRuntime().exec(command);
				BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
				String line;
				while ((line = br.readLine()) != null) {
					if (line.contains("sd")) {
						return "scsi";
					}
					if (line.contains("hd")) {
						return "ide";
					}
				}
				br.close();
			} catch (IOException e) {
			}
		}
		return "unkonwn"; // 未知类型
	}

	/**
	 * Main Class.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("Operation System=" + getOsName());
		System.out.println("HD SerialNo=" + getHDSerialNo());
	}
}</pre><br /><br />现在在本地机器ubuntu上可以运行,但是放到其他比如Centos或suse上获取不了。<br />根本原因是通过java调用的一个SHELL>"hdparm -i /dev/sda1" ,这个命令对于SCSI 的硬盘好像支持不了。<br /><br />有谁做过的给个建议阿。好多人说用c写个底层的，然后通过jni调用。那样不是系统得有c的运行环境吗？<br />我觉得一个util类有这个必要吗？
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/232444#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 25 Aug 2008 14:38:24 +0800</pubDate>
        <link>http://www.javaeye.com/topic/232444</link>
        <guid>http://www.javaeye.com/topic/232444</guid>
      </item>
      <item>
        <title>一个关于Hibernate的优化实例：从HQL到QBC，从QBC到QBE，再到“增强的”QBE</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://movingboy.javaeye.com">movingboy</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233664" style="color:red;">http://www.javaeye.com/topic/233664</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          先解释一下标题的含义：为了实现一个组合条件查询，先是使用HQL书写，然后改用Query by Criteria方式，再尝试Query by Example，最后自己实现了一个增强的Example类来解决问题。<br /><br />关于此问题的起源请阅读我以前的一个帖子：<a href="http://www.javaeye.com/post/523791" target="_blank">http://www.javaeye.com/post/523791</a>。在该帖子中已经实现了从HQL到QBC的转变，在这里就不再重复了。<br /><br />在上一个帖子中没有模型类Product及Category的代码，为了方便讨论补充如下：<br /><br /><pre name="code" class="java">public class Category {
  private Long id;
  private String name; //类别名称

  //Other code omitted
}

public class Product {
  private Long id;
  private String name;       //商品名称
  private Category category; //商品类别
  private Date expDate;      //有效期
  private Float price;       //单价

  //Other code omitted
}
</pre><br /><br />从前一个帖子中可以看到，使用QBC后代码有所减少，但还是得把构造查询条件的代码写死，这非常不爽。重读了《Java Persistence with Hibernate》一书，发觉QBE是个好东东，于是尝试用改造代码如下：<br /><br /><pre name="code" class="java">	public List&lt;Product> getProducts(Product product) {
		final Example exampleProduct =
		  Example.create(product).
		    enableLike(MatchMode.ANYWHERE).
                    excludeZeroes();

		return (List&lt;Product>) getHibernateTemplate().execute(
		  new HibernateCallback() {
		    public Object doInHibernate(Session session) throws HibernateException {
		    	Criteria crit =
		    	  session.createCriteria(Product.class).
		    	  add(exampleProduct);
		    	return crit.list();
		    }
		  }
		);
	}
</pre><br /><br />代码非常简洁啊！我只要new一个Product实例，然后把要查询的条件值赋值到相应到属性上，如果某项条件未指定则相应的属性保留为默认的空值，将该实例传递给上面的getProducts方法，就能得到需要的结果了。超爽！<br /><br />但是我却没办法把这段代码用在产品中，这是因为QBE有着严重的局限性：<br />1.不能查询指定在关联对象的属性上的条件。比如我想仅列出商品类别名称包括xyz的商品，代码如下：<br /><br /><pre name="code" class="java">Category category = new Category();
category.setName("xyz");
Product product = new Product();
product.setCategory(category);

List&lt;Product> products = getProducts(product);
</pre><br /><br />运行这段代码会列出所有的商品。<br /><br />2.除了字符串条件可以调用enableLike()方法改用模糊查询外，其它数据类型的条件都只能等值比较。比如我无法查询所有有效的商品（有效期≥当前日期）。<br /><br />难道就没有办法了吗？经过一番搜索，终于在Hibernate的官网论坛上找到一篇文章：<a href="http://forum.hibernate.org/viewtopic.php?t=942872" target="_blank">http://forum.hibernate.org/viewtopic.php?t=942872</a>。在该文章中，Dencel写了一个AssociationExample，经过大家的完善，终于解决了查询指定在关联对象的属性上的条件的问题。其主要的奥妙在于：<br /><br /><pre name="code" class="java">
//Hibernate的原版Example
//如果属性类型是关联的实体，则忽略
	private boolean isPropertyIncluded(Object value, String name, Type type) {
		return !excludedProperties.contains(name) &&
			!type.isAssociationType() &&
			selector.include(value, name, type);
	}

//改版的AssociationExample
  private boolean includeAssociations = true;

  public boolean isIncludeAssociations()
  {
    return includeAssociations;
  }

  public void setIncludeAssociations(boolean includeAssociations)
  {
    this.includeAssociations = includeAssociations;
  }

//如果属性类型是关联的实体，且该关联是一对一或多对一，且includeAssociations为true，则包括该属性
  private boolean isPropertyIncluded(Object value, String name, Type type) {
    return
      !excludedProperties.contains(name) &&
      selector.include(value, name, type) &&
      (!type.isAssociationType() ||
        (type.isAssociationType() &&
          includeAssociations &&
          !type.isCollectionType()));
  }
</pre><br /><br />解决了前面提到的第一个问题，第二个问题又怎么办呢？我想到一个办法：如果某个条件要使用其它的比较方式（比如大于等于），提供一个方法让用户为该属性指定比较方法，对于其它属性仍采用缺省的查询/比较方法：<br /><br /><pre name="code" class="java">
//Hibernate原版的Example
  protected void appendPropertyCondition(
    String propertyName,
    Object propertyValue,
    Criteria criteria,
    CriteriaQuery cq,
    StringBuffer buf)
  throws HibernateException {
    Criterion crit;
    if ( propertyValue!=null ) {
//当属性值不为空时，如果是字符串且指定为模糊查询，则使用模糊查询，否则使用等值比较
      boolean isString = propertyValue instanceof String;
      SimpleExpression se = ( isLikeEnabled && isString ) ?
        Restrictions.like(propertyName, propertyValue) :
        Restrictions.eq(propertyName, propertyValue);
      crit = ( isIgnoreCaseEnabled && isString ) ?
        se.ignoreCase() : se;
    }
    else {
      crit = Restrictions.isNull(propertyName);
    }
    String critCondition = crit.toSqlString(criteria, cq);
    if ( buf.length()>1 && critCondition.trim().length()>0 ) buf.append(" and ");
    buf.append(critCondition);
  }


//增强后的EnhancedExample
  private static final RestrictionHolder holder = new DefaultRestrictionHolder();

  /**
   * Restriction strategy definitions
   */
  public static enum RestrictionStrategy {eq, ne, gt, lt, ge, le}

  /**
   * Restriction strategy holder for the query criteria
   */
  public static interface RestrictionHolder {
  	/**
  	 * Set a restriction strategy for a POJO's property
  	 */
    public RestrictionHolder set(String propertyName, RestrictionStrategy strategy);

    /**
     * Get the restriction strategy of the property
     */
    public RestrictionStrategy get(String propertyName);
  }

  static final class DefaultRestrictionHolder implements RestrictionHolder {
		private Map&lt;String, RestrictionStrategy> strategies = new HashMap&lt;String, RestrictionStrategy>();

    public RestrictionHolder set(String propertyName, RestrictionStrategy strategy) {
      strategies.put(propertyName, strategy);
      return this;
    }

    public RestrictionStrategy get(String propertyName) {
      return strategies.get(propertyName);
    }
  }

  /**
   * Get the restriction strategy holder
   */
  public RestrictionHolder getRestrictionHolder() {
    return holder;
  }

  protected void appendPropertyCondition(
    String propertyName,
    Object propertyValue,
    Criteria criteria,
    CriteriaQuery cq,
    StringBuffer buf)
  throws HibernateException {
    Criterion crit;
    if ( propertyValue!=null ) {
//当属性值不为空时，如果为该属性指定了比较条件，则使用指定的比较条件
      RestrictionStrategy strategy = holder.get(propertyName);
      if ( strategy != null ) {
  	switch(strategy) {
    	//case eq: crit = Restrictions.eq(propertyName, propertyValue);
    	case ne: crit = Restrictions.ne(propertyName, propertyValue); break;
    	case gt: crit = Restrictions.gt(propertyName, propertyValue); break;
    	case lt: crit = Restrictions.lt(propertyName, propertyValue); break;
    	case ge: crit = Restrictions.ge(propertyName, propertyValue); break;
    	case le: crit = Restrictions.le(propertyName, propertyValue); break;
    	default: crit = Restrictions.eq(propertyName, propertyValue);
        };
      }
      else {
//否则使用默认的比较条件：如果是字符串且指定为模糊查询，则使用模糊查询，否则使用等值比较
	boolean isString = propertyValue instanceof String;
	SimpleExpression se = ( isLikeEnabled && isString ) ?
	  Restrictions.like(propertyName, propertyValue) :
	  Restrictions.eq(propertyName, propertyValue);
	crit = ( isIgnoreCaseEnabled && isString ) ?
	  se.ignoreCase() : se;
      }
    }
    else {
      crit = Restrictions.isNull(propertyName);
    }
    String critCondition = crit.toSqlString(criteria, cq);
    if ( buf.length()>1 && critCondition.trim().length()>0 ) buf.append(" and ");
    buf.append(critCondition);
  }
</pre><br /><br />于是前面getProducts方法只需要简单修改一下：<br /><br /><pre name="code" class="java">	public List&lt;Product> getProducts(Product product) {
		//改用EnhancedExample来允许关联对象的条件查询
		final EnhancedExample exampleProduct =
		  EnhancedExample.create(product).
		    enableLike(MatchMode.ANYWHERE).
                    excludeZeroes();
		  //指定expDate属性使用大于等于比较方法
		exampleProduct.getRestrictionHolder().
		  set("expDate", EnhancedExample.RestrictionStrategy.ge);

		return (List&lt;Product>) getHibernateTemplate().execute(
		  new HibernateCallback() {
		    public Object doInHibernate(Session session) throws HibernateException {
		    	Criteria crit =
		    	  session.createCriteria(Product.class).
		    	  add(exampleProduct);
		    	return crit.list();
		    }
		  }
		);
	}
</pre><br /><br />经过以上改进，QBE的实用性大大提高，能够真正解决较大多数的组合查询问题。<br /><br />已知的问题：以上“增强的”QBE还无法解决范围查询（比如价格在0到1000之间），这是因为一个属性只能携带一个值（你不可能指定两个值给Product.price属性）。这种情况下需要修改getProducts方法，增加参数把价格范围传递进来，再以QBC方式把相应的条件加到crit变量上。范例代码就不再给出了。<br /><br />完整的EnhancedExample源码请见附件。
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/233664#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 00:04:40 +0800</pubDate>
        <link>http://www.javaeye.com/topic/233664</link>
        <guid>http://www.javaeye.com/topic/233664</guid>
      </item>
      <item>
        <title>ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://andyao.javaeye.com">andyao</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/234101" style="color:red;">http://www.javaeye.com/topic/234101</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h3>简介</h3>
<p><a href="../153171" target="_blank">实战一</a>
, <a href="../154092" target="_blank">实战二</a>
介绍了ActiveMQ的基本概念和配置方式.</p>
<p>本篇将通过一个实例介绍使用spring发送,消费topic, queue类型消息的方法. 不懂topic和queue的google 之.</p>
<p>&nbsp;</p>
<p><a href="../../../upload/picture/pic/20785/485ba4ca-70db-3a46-a5c8-1cd3d9b81f65.gif" target="_blank"><img src="../../../upload/picture/pic/20785/485ba4ca-70db-3a46-a5c8-1cd3d9b81f65.gif" height="209" alt="" width="387" />
</a>
</p>
<p>如图示, TOPIC和QUEUE分别代表一个topic和一个queue消息通道. </p>
<ol>
<li>TopicMessageProducer向topic发送消息, TopicConsumerA和TopicConsumerB则从topic消费消息.</li>
<li>QueueMessageProducer向Queue发送消息, QueueConsumer从Queue中消费消息</li>
</ol>
<h3>Spring整合JMS</h3>
<p>就像对orm, web的支持一样, spring同样支持jms, 为整合jms到已有的项目提供了很多便利的方法. 本篇主要讲实战, 是所以先从配置开始, spring配置jms基本上需要8个部分.</p>
<ol>
<li>ConnectionFactory. 和jms服务器的连接, 可以是外部的jms server, 也可以使用embedded ActiveMQ Broker.</li>
<li>Destination. 有topic和queue两种方式.</li>
<li>JmsTemplate. spring提供的jms模板.</li>
<li>MessageConverter. 消息转换器.</li>
<li>MessageProducer. 消息生产者.</li>
<li>MessageConsumer. 消息消费者.</li>
<li>MessageListener. 消息监听器</li>
<li>MessageListenerContainer. 消息监听容器</li>
</ol>
<p>下面以实例的方式介绍上面8个部分.</p>
<h4>1. ConnectionFactory</h4>
<pre name="code" class="xml">&lt;amq:connectionFactory id="jmsConnectionFactory" brokerURL="vm://localhost" /&gt;</pre>
<p>&nbsp;brokerURL是指要连接的activeMQ server的地址, activeMQ提供了多种brokerURL, 集体可参见文档.一般我们使用嵌套的ActiveMQ server. 配置如下, 这个配置使用消息的存储机制, 服务器重启也不会丢失消息.</p>
<pre name="code" class="xml">&lt;!--  embedded ActiveMQ Broker --&gt;
	&lt;amq:broker useJmx="false" persistent="true"&gt;
		&lt;amq:persistenceAdapter&gt;
			&lt;amq:amqPersistenceAdapter directory="d:/amq"/&gt;
		&lt;/amq:persistenceAdapter&gt;
		&lt;amq:transportConnectors&gt;
			&lt;amq:transportConnector uri="tcp://localhost:0" /&gt;
		&lt;/amq:transportConnectors&gt;
	&lt;/amq:broker&gt;</pre>
<h4>&nbsp;2. Destination</h4>
<p>&nbsp;在实例中我们使用了两种destination</p>
<pre name="code" class="xml">&lt;!--  ActiveMQ destinations  --&gt;
&lt;!--  使用topic方式--&gt;
&lt;amq:topic name="TOPIC" physicalName="JMS-TEST-TOPIC" /&gt;
&lt;!--  使用Queue方式--&gt;
&lt;amq:queue name="QUEUE" physicalName="JMS-TEST-QUEUE" /&gt;</pre>
<h4>&nbsp;3. JmsTemplate</h4>
<pre name="code" class="xml">&lt;!--  Spring JmsTemplate config --&gt;
	&lt;bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt;
		&lt;property name="connectionFactory"&gt;
			&lt;!--  lets wrap in a pool to avoid creating a connection per send --&gt;
			&lt;bean class="org.springframework.jms.connection.SingleConnectionFactory"&gt;
				&lt;property name="targetConnectionFactory" ref="jmsConnectionFactory" /&gt;
			&lt;/bean&gt;
		&lt;/property&gt;
		&lt;!-- custom MessageConverter --&gt;
		&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
	&lt;/bean&gt;</pre>
<h4>
&nbsp;
4. MessageConverter</h4>
<p>&nbsp;&nbsp; MessageConverter实现的是org.springframework.jms.support.converter.MessageConverter接口, 提供消息的转换功能. DefaultMessageConverter的实现见附件.</p>
<pre name="code" class="xml">&lt;bean id="defaultMessageConverter" class="com.andyao.activemq.DefaultMessageConverter" /&gt;</pre>
<h4>&nbsp; 5. MessageProducer</h4>
<p>&nbsp;&nbsp; 实例拥有两个消息生产者, 消息生产者都是POJO, 实现见附件.</p>
<pre name="code" class="xml">&lt;!-- POJO which send Message uses  Spring JmsTemplate --&gt;
	&lt;bean id="topicMessageProducer" class="com.andyao.activemq.TopicMessageProducer"&gt;
		&lt;property name="template" ref="jmsTemplate" /&gt;
		&lt;property name="destination" ref="TOPIC" /&gt;
	&lt;/bean&gt;
	&lt;bean id="queueMessageProducer" class="com.andyao.activemq.QueuMessageProducer"&gt;
		&lt;property name="template" ref="jmsTemplate" /&gt;
		&lt;property name="destination" ref="QUEUE" /&gt;
	&lt;/bean&gt;</pre>
<h4>&nbsp;6. MessageConsumer</h4>
<p>&nbsp;TOPIC通道有两个消息消费者, QUEUE有一个消息消费者</p>
<pre name="code" class="xml">&lt;!--  Message Driven POJO (MDP) --&gt;
    &lt;!-- consumer1 for topic a --&gt;
    &lt;bean id="topicConsumerA" class="com.andyao.activemq.TopicConsumerA" /&gt;
    &lt;!-- consumer2 for topic a --&gt;
    &lt;bean id="topicConsumerB" class="com.andyao.activemq.TopicConsumerB" /&gt;
    &lt;!-- consumer for queue --&gt;
    &lt;bean id="queueConsumer" class="com.andyao.activemq.QueueConsumer" /&gt;</pre>
<h4>
&nbsp;
7. MessageListener</h4>
<p>每一个消息消费者都对应一个MessageListener</p>
<pre name="code" class="xml">&lt;bean id="topicListenerA" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"&gt;
		&lt;constructor-arg ref="topicConsumerA" /&gt;
		&lt;!--  may be other method --&gt;
		&lt;property name="defaultListenerMethod" value="receive" /&gt;
		&lt;!-- custom MessageConverter define --&gt;
		&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
	&lt;/bean&gt;

	&lt;bean id="topicListenerB" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"&gt;
		&lt;constructor-arg ref="topicConsumerB" /&gt;
		&lt;!--  may be other method --&gt;
		&lt;property name="defaultListenerMethod" value="receive" /&gt;
		&lt;!-- custom MessageConverter define --&gt;
		&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
	&lt;/bean&gt;

    &lt;bean id="queueListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"&gt;
		&lt;constructor-arg ref="queueConsumer" /&gt;
		&lt;!--  may be other method --&gt;
		&lt;property name="defaultListenerMethod" value="receive" /&gt;
		&lt;!-- custom MessageConverter define --&gt;
		&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
	&lt;/bean&gt;</pre>
<h4>&nbsp;8. MessageListenerContainer</h4>
<p>&nbsp;有几个MessageListener既有几个MessageListenerContainer</p>
<pre name="code" class="xml">&lt;bean id="topicListenerContainerA" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
		&lt;property name="connectionFactory" ref="jmsConnectionFactory" /&gt;
		&lt;property name="destination" ref="TOPIC" /&gt;
		&lt;property name="messageListener" ref="topicListenerA" /&gt;
	&lt;/bean&gt;

    &lt;bean id="topicListenerContainerB" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
		&lt;property name="connectionFactory" ref="jmsConnectionFactory" /&gt;
		&lt;property name="destination" ref="TOPIC" /&gt;
		&lt;property name="messageListener" ref="topicListenerB" /&gt;
	&lt;/bean&gt;
    
    &lt;bean id="queueListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
		&lt;property name="connectionFactory" ref="jmsConnectionFactory" /&gt;
		&lt;property name="destination" ref="QUEUE" /&gt;
		&lt;property name="messageListener" ref="queueListener" /&gt;
	&lt;/bean&gt;</pre>
<h3>
&nbsp;
Summary</h3>
<p>写spring配置文件的时候, 要把MessageProducer, MessageConsumer,MessageListener,MessageListenerContainer几个地方弄清楚:</p>
<ol>
<li>可以有一个或者多个消息生产者向同一个destination发送消息.</li>
<li>queue类型的只能有一个消息消费者.</li>
<li>topic类型的可以有多个消息消费者.</li>
<li>每个消费者对应一个MessageListener和一个MessageListenerContainer.</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/234101#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 18:21:19 +0800</pubDate>
        <link>http://www.javaeye.com/topic/234101</link>
        <guid>http://www.javaeye.com/topic/234101</guid>
      </item>
      <item>
        <title>AOP功能和AOP框架</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://the3oooo.javaeye.com">Joo</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233743" style="color:red;">http://www.javaeye.com/topic/233743</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这几天一直在思考在一个应用上实现AOP功能到底和实现独立的一个AOP框架有什么不同。利用JDK动态代理或CGLIB甚至用Servlet Filter就能实现简单的AOP功能，那么AOP框架的价值究竟在哪里? <br />表面上来看,使用框架除了应用开发人员不需要知道CGLIB原理,代码中不会出现implements MethodInterceptor或Enhancer.Create()之外,找不到框架可以做而用CGLIB代码不能做的事情啊.BOSS让我提炼一个简单的AOP,一开始我准备包装一下CGLIB API做,但后来发现如果是实现一般的AOP功能,CGLIB已经可以完全胜任.如果要做一个AOP框架,我不知道应该往什么方向努力啊!!!!<br /><br />另,看不明白CGLIB中Dispatcher和LazyLoader的用法啊,望指点.
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/233743#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 10:30:39 +0800</pubDate>
        <link>http://www.javaeye.com/topic/233743</link>
        <guid>http://www.javaeye.com/topic/233743</guid>
      </item>
      <item>
        <title>忘掉普元EOS、构建自己的企业级快速应用开发平台</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://longlongriver.javaeye.com">longlongriver</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/232219" style="color:red;">http://www.javaeye.com/topic/232219</a>&nbsp;
          发表时间: 2008年08月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong><span style="font-size: x-small;"><em><span style="color: #ff0000; font-size: small;">希望这篇文章能够对那些正在或即将开发自己团队的J2EE应用快速开发平台（工作流＋代码生成器）的个人或公司能有所启发！</span>
</em>
&nbsp;&nbsp;&nbsp;</span>
</strong>
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 像EOS这样动辄几十上百万的平台不是每个公司都愿意花钱去买的！因此构建一套穷人级的企业快速开发平台成了很多团队的首选，而对于小团队来说，构建一套自己可以维护的开发平台才是最重要的。下面，我将以我的平台的开发过程为例来详细解析这个过程！<strong><span style="font-size: x-small;"> &nbsp; </span>
</strong>
</p>
<p><span style="font-size: small;"><strong><span>&ldquo;如果能把项目中大量的代码编写工作变得轻松，是多好的一件事!</span>
</strong>
&nbsp;"</span>
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
在使用了AppFuse之后，我有个想法，能不能利用velocity这个优秀的模板引擎，用一种更加直观的模式，把开发项目中的重复代码让它自动生成，
生成之后的基础代码，按照实际的需求稍作修改便可以运行，极大的提高工作效率。这样的话，程序员就可以从大量的重复劳动中解放出来，将精力更多的投入到业
务分析及学习中。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个想法一直在我的脑海里横亘不去，尤其在做了大量的重复模块后，深刻体会了重复Coding的那种浪费生命的痛苦后，这种冲动尤为强烈。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 离开旧公司，到了新公司之后，由于职位和公司定位的不同，让我有时间开始把快速开发平台和自动代码生成器的开发真正的摆上开发日程上了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: medium;"><strong><span style="text-decoration: underline;">第一步</span>
</strong>
</span>
，自动代码生成器生成
的是业务模块，那么底层必须有一套框架能够为它提供支撑，而且这套基础框架要足够灵活，并且和单个模块的耦合性要比较弱。要解耦模块之间的联系，势必要用
到MVC分层设计。感谢Java的开放性，使它有这么许许多多的MVC框架可以使用。我采用的当然是目前最流行的
SSH（Struts＋Spring＋Hibernate）的组合（以前项目一直在用，也有些成熟的积累），花了三个月的时间，通过一个项目的实际应用来
使这个框架基本成型。其目前功能包括：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
1：灵活完善的权限管理功能（包括用户管理、角色管理、组织机构管理、资源管理、资源角色映射管理...）。原来计划采用开源的JGuard来托管这部分
的功能，因为一些特殊的原因放弃了（考虑要和工作流引擎的权限部分做集成），只采用了其权限管理的一些设计思想。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
2：基于Spring的AOP实现的日志和权限管理（通过Spring的代理也将Struts的Action托管了，使的对Action的调用也能被
AOP侦测到），这样对每个功能的调用，如果需要日志纪录的话，之间将其配置到Spring的配置文件中就可以了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3：UI上实现了类似.NET的Validation验证，这点很重要，想必大家都深刻体会到利用JavaScript或Struts的验证机制来实现前端页面数据验证的痛苦了吧：），我们实现的功能如下图所示：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/1.GIF" alt="" />
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、多套UI风格样式。这个不是很必须，但是作为一套成功的系统，良好的用户体验也是必不可少的。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5、支撑模块：报表引擎（基于JasperReport实现的B/S版本报表），流程引擎（<span style="color: #ff0000; font-size: large;"><span style="text-decoration: underline;"><strong>其实就我个人来看，工作流引擎才是这套系统的灵魂</strong>
<strong>，有了它，所有流程性应用包括表单、业务流、权限都可以通过配置并结合Beanshell脚本来获得</strong>
</span>
</span>
，但由于我们集成的是一套反编译重构的商用流程引擎系统，在这里就不再详细描述了 ，呵呵：），有盗版之嫌啊）,以下是我们报表和流程设计器的一些截图：</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/EntryImages/20080826/workflow2.GIF" height="969" alt="" width="1207" />
</p>
<p>&nbsp;</p>
<p align="center"><strong>工作流引擎截图</strong>
</p>
<p>&nbsp;</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/EntryImages/20080825/report.GIF" alt="" style="width: 904px; height: 441px;" />
</p>
<p align="center"><strong>报表截图</strong>
</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 6、i18n的支持，由于我们有很多国外的客户，这块是必须的。</p>
<p>&nbsp;</p>
<p>有了这个基础支撑平台之后，就可以开始着手开放我们的代码生成器了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="text-decoration: underline;"><span style="font-size: medium;">&nbsp;&nbsp;&nbsp; 第二步</span>
</span>
</strong>
：开发代码生成器。
AppFuse基于Ant的自动代码生成模式让我深恶痛绝，究其原因，一句话－－&ldquo;不够人性化&rdquo;，我们做的首先必须考虑可用性，因此决定采用可视化的UI
模式。由于我用的是NetBean编辑器，做可视化的Swing开发不成问题（这点要感谢SUN啊，出了个和VB一样简单的IDE）。我实现的代码生成器
的界面如下：<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/2.GIF" height="483" alt="" style="width: 589px; height: 555px;" width="443" />
</p>
<p>&nbsp;&nbsp; <img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/3.GIF" alt="" />
</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/4.GIF" alt="" />
</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/5.GIF" alt="" />
</p>
<p>&nbsp; <img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/6.GIF" alt="" />
</p>
<p>怎么样？是不是够傻瓜化啊？呵呵，是个人都能用啊！</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
从上面大家可以看到，我们这个代码生成器和Hibernate的POJO对象生成工具类似，也是基于数据库的模型来生成代码的，不同的是，我们生成的代码
范围更广，不仅包括了POJO对象暨相应的hbm.xml文件，另外还包括相应的DAO（Server层）、相应的Action、Form类、相关的
JSP文件（list页面、edit页面、Excel导出页面等等）、资源文件及相关的Struts和Spring的配置子文件（Struts和
Spring均支撑将配置拆分成多个配置，我们利用这种特性来减低模块之间的耦合性。）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至于数据库模型的获得，可以利用JDBC的<strong><em><span style="text-decoration: underline;">MetaData（元数据模型）</span>
</em>
</strong>
的功能来获得，我们目前维护了表的完整的主键、外键关系（父子表）</p>
<p>&nbsp;第三步：配置模板。有了可视化的数据库表映射模型，也获得了数据库表及其主外键关系的详细信息，接下来当然是根据这些信息来生成代码了。这里我们用了强大的<strong><em><span style="text-decoration: underline;">Velocity模板</span>
</em>
</strong>
技术，这样不仅可以灵活的处理复杂的表映射对象之间的关系，也能够灵活的进行变更升级。<span style="text-decoration: underline;">而且我们能够通过所获得的数据库模型，在页面上自动实现基于Javascript的数据验证&ldquo;非空验证、字符长度验证、数字验证，日期验证&rdquo;。</span>
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
呵呵，通过以上3个步骤的工作，我们的基础开发平台和自动代码生成器就大功告成了！目前我们生成的代码可以直接编译通过，通过简单的系统配置后，可以直接在服务器上跑！
由于模板种类多，而且模板中自动实现的代码功能已经非常完善了，所以一些特殊的业务需求只需要在自动生成的代码基础上做简单修改就可以了！</p>
<p><span style="color: #333399; font-size: small;">&nbsp;&nbsp;<strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
基础开发平台和代码生成器投入使用后，对我们项目开发的资源投入的改善是非常明细的，目前基于基础平台和代码生成器的配合，我们已经做了6、7个系统了，平均每个系统的
开发时间至少要比以前节约40％，有的项目甚至达到了80％以上（我们最高的一天，处理了40多个表的增、删、该、查的功能，及中文本地化）。而且，另外
很重要的一点，生成的代码无形中统一了程序员的设计风格，我们通过这套开发机制，能够最大限度的保证我们开发的系统质量，保证模块可以在不同系统之间的自
由迁移，最大限度的实现复用！在项目开发中节省出来的大量时间，也让我们可以去研究更多的开源中间件和系统，来增强我们的基础平台，从而形成一个良性的循
环！</strong>
</span>
</p>
<p>&nbsp;我们做了多套模板，能够针对单表操作，及父子表操作来自由组合搭配。以下就是我们系统的一些功能截图，除了中文化之外，基本上没有修改：</p>
<p><strong><span style="color: #ff0000; font-size: small;">单表操作：</span>
</strong>
</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/7.GIF" alt="" />
</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/8.GIF" alt="" />
</p>
<p><span style="color: #ff0000; font-size: medium;"><strong>父子表关联操作：</strong>
</span>
</p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/LongLongRiver/10.GIF" alt="" />
</p>
<p><span style="font-size: small;"><em><strong>&nbsp;</strong>
</em>
</span>
</p>
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/232219#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 25 Aug 2008 09:44:43 +0800</pubDate>
        <link>http://www.javaeye.com/topic/232219</link>
        <guid>http://www.javaeye.com/topic/232219</guid>
      </item>
      <item>
        <title>DesignPattern学习-----Observer</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://ivan-pig.javaeye.com">Ivan_Pig</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233984" style="color:red;">http://www.javaeye.com/topic/233984</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Observer直译为中文为观察者。所以此模式又称为观察者模式（废话。）不过一直很疑惑，我感觉这个名字起得不好，给人误解很大，特别是初学者。我想大部分人的想法应该和我一样，我第一次看到观察者模式就会想到，观察者观察者，那么肯定观察者是主体了。其实不然。被观察者才是主体。<br />     就小孩睡觉这个例子，如果按观察者的想法，那就观察嘛！！！怎么观察，小孩在睡觉，我就在那观察，他眼一睁，啊，要喝奶了。赶紧去泡奶粉。。。。这个显然就不正常。傻子才这么干。。。。<br />     实际上是你该干嘛就干嘛去，小孩醒了，一哭要喝奶了，你就去泡奶吧。<br />     所以我认为观察者模式叫Call模式或者Call-Response模式更恰当。<br />     下面看程序，模拟找工作。。。。雇主通知他要招聘的雇员，雇员得到通知后做出响应。<br />     先是两个接口，Employer和Employee。<br /><pre name="code" class="java">
package pig.pattern.Observer;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:31:33
 * To change this template use File | Settings | File Templates.
 */
public interface Employer {
    void agree_call();           
    void agree(Employee employee);  //相当于swing里的add***Listener()
}
</pre><br /><br /><pre name="code" class="java">
package pig.pattern.Observer;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:32:14
 * To change this template use File | Settings | File Templates.
 */
public interface Employee {
    void response(EmployEvent event);
//这个相当于ActiongListener里面的actionPerformed(ActionEvent event)
}
</pre><br />再来相应的实现类<br /><pre name="code" class="java">
package pig.pattern.Observer;

import java.util.List;
import java.util.ArrayList;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:32:51
 * To change this template use File | Settings | File Templates.
 */
public class Employer_1 implements Employer{
    private List&lt;Employee> employees = new ArrayList&lt;Employee>();
    private EmployEvent event;

    public void agree(Employee employee){
        employees.add(employee);
    }

    public void agree_call() {
        event = new EmployEvent();
        event.setEmployer_name(this.getClass().getSimpleName());
        for(Employee e : employees){
            e.response(event);
        }
    }
}
</pre><br /><pre name="code" class="java">
package pig.pattern.Observer;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:49:22
 * To change this template use File | Settings | File Templates.
 */
public class Employee_1 implements Employee{
    public void response(EmployEvent event) {
        System.out.println("Oh,I'm lucky.I'm employed by " + event.getEmployer_name());
    }
}
</pre><br /><pre name="code" class="java">
package pig.pattern.Observer;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:49:22
 * To change this template use File | Settings | File Templates.
 */
public class Employee_2 implements Employee{
    public void response(EmployEvent event) {
        System.out.println("Yeah,I'm employed by " + event.getEmployer_name());
    }
}
</pre><br /><br />再来事件类<br /><pre name="code" class="java">
package pig.pattern.Observer;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:39:48
 * To change this template use File | Settings | File Templates.
 */
public class EmployEvent {
    private String employer_name;

    public String getEmployer_name() {
        return employer_name;
    }

    public void setEmployer_name(String employer_name) {
        this.employer_name = employer_name;
    }
}
</pre><br />最后测试一下。<br /><pre name="code" class="java">
package pig.pattern.Observer;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2008-8-28
 * Time: 14:51:00
 * To change this template use File | Settings | File Templates.
 */
public class Test {
    public static void main(String[] args){
        Employer e_1 = new Employer_1();
        e_1.agree(new Employee_1());
        e_1.agree(new Employee_2());
        e_1.agree_call();
    }
}
</pre><br />Employer在众多的简历里面挑选出自己满意的，然后agree到自己的通知列中(list)，全部都确认后，然后一起去call所有的这些应聘者，各个应聘者做出不同的反应。EmployEvent就相当于通知书一样，里面保存了Employer的名称，不然你怎么知道你是被哪个Employer聘了？<br />这还是说明，<span style="color: red">观察者(Employee)并不是主体，被观察者(Employer)才是主体</span>。如果Employee是主体，那是不是你投完简历以后就天天跟着那个Employer，他一天不做出决定，你就一天不停了？<br />至于用到哪儿，根据代码应该就能猜得出来。一个对象的改变会影响其他对象的响应，而且对象个数不确定。<br />很粗糙的代码，只想说别被名字唬到了。。。。
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/233984#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 15:42:10 +0800</pubDate>
        <link>http://www.javaeye.com/topic/233984</link>
        <guid>http://www.javaeye.com/topic/233984</guid>
      </item>
      <item>
        <title>通用的权限模型有可能吗？</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jasongreen.javaeye.com">jasongreen</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/232497" style="color:red;">http://www.javaeye.com/topic/232497</a>&nbsp;
          发表时间: 2008年08月25日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          权限模型设计时，一般是用户可以是多个角色，每个角色分配一组权限，每个用户还可以分配几个额外权限。<br /><br />在权限分配的页面上，一般还需要将权限按照树状的层次展现出来，如“用户管理"节点下有“创建用户”“删除用户”“修改用户” 几个权限。<br /><br />然而权限对象本身是特殊的，有时权限针对页面，有时权限针对的是数据的范围。所以我考虑，是否可以把权限描述为一个接口？<br /><br /><pre name="code" class="java">class User{
  List&lt;Role> roles;
  List&lt;Permission> additionalPermission;
}

class Role{
  List&lt;Permission> permissions;
}

interface Permission{
  String getName(Locale locale)
  String getDescription(Locale locale)
}

class WebPermission{
  List&lt;Pattern> getAccessibleUrl();
}</pre><br /><br />目前在Light-Commons 的权限框架中，是使用 IUser.getPermissionKeys() 来获取用户权限key列表，这些key对应配置文件中定义的一些可访问url。但对于其他的权限逻辑无法控制。<br />如何才能编写一个通用的权限模型呢？<br /><br />另外，我觉得一个应用所对应的权限大部分是固定的，应该由配置文件读取，而不是由数据库读取。但是有些系统权限也需要是动态的，比如创建了一个部门后，也就创建了这个部门的一些操作权限，可以将这些权限分配给某个人。<br /><br />另外，权限里面还有一种特殊的类型，比如“操作自己的数据”，“操作自己所在部门的数据”，“操作自己下属的数据”，这些权限不是具体到控制对象的，而是表达一种与控制对象的关联关系。一般来说都是硬编码实现的。可复用很难。<br /><br />基本上，对于权限的逻辑部分，我认为复用很难，但是整个权限部分整理一个模板，还是有可能的。至少页面层的模板应该是可以的，如创建用户页面，权限分配页面。如：但需要后台的权限相关对象匹配。
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/232497#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 25 Aug 2008 17:15:36 +0800</pubDate>
        <link>http://www.javaeye.com/topic/232497</link>
        <guid>http://www.javaeye.com/topic/232497</guid>
      </item>
      <item>
        <title>Dwr2+Struts2+Spring2.5+Hibernate3完美整合－－用户登录注册系统</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jackzhangyunjie.javaeye.com">jackzhangyunjie</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/231797" style="color:red;">http://www.javaeye.com/topic/231797</a>&nbsp;
          发表时间: 2008年08月23日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          　　用户注册和登录是每个系统的必须存在的一部分，基于Dwr+Struts2+Spring+Hibernate写了一个用户登录注册系统。<br />　　其中用Dwr去进行用户注册的用户是否存在的验证。<br />　　全部业务控制交由Spring去进行处理。事务处理也交由Spring去管理。<br />　　压缩文件中不包含Jar文件(由于全部的Jar将近12M，不能全部上传)，所用到的Jar目录为,工程中再也不会出现由于MyEclipse自动整合而出现的大量Jar文件<img src="/images/smiles/icon_biggrin.gif"/>：<br /><pre name="code" class="java">

//如果不用，启动时不会出错，但使用Dwr时，会抛出异常：java.lang.NoClassDefFoundError: antlr/ANTLRException
antlr-2.7.2.jar　

//如果不用此包，在启动时会抛出： nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/Type
asm.jar

//如果不用此包，在启动时抛出：nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
aspectjweaver.jar

//如果不用此包，在启动时抛出：nested exception is java.lang.NoClassDefFoundError: net/sf/cglib/proxy/CallbackFilter
cglib-2.1.3.jar

//如果不用此包，在启动时抛出：nested exception is java.lang.NoClassDefFoundError: org/apache/commons/collections/SequencedHashMap
commons-collections-3.1.jar

//这个似乎可以不用的
commons-fileupload-1.2.1.jar

//这个就不用说啦，几乎所有框架都要使用的
commons-logging-1.0.4.jar 

//如果不用此包会抛出：java.lang.NoClassDefFoundError: org/dom4j/DocumentException
dom4j-1.6.1.jar

//dwr必须
dwr.jar 


//不用此包，在启动时招聘：java.lang.NoClassDefFoundError: javax/transaction/TransactionManager
jta.jar

//Mysql　JDBC驱动
mysql-connector.jar

//Hibernate必须使用，注意此包是包含全部的。
hibernate3.jar

//Spring整体包
spring.jar            

//struts2必须               
freemarker-2.3.8.jar   
//struts2必须
ognl-2.6.11.jar       
//struts2核心包
struts2-core-2.0.11.2.jar
//struts2整合Spring插件  
struts2-spring-plugin-2.0.11.2.jar 
//struts2必须
xwork-2.0.5.jar 
</pre><br /><br />　　数据库设计(使用MySql数据库)：<br /><pre name="code" class="java">
create table user
(
  id varchar(32) not null,
  userName varchar(20),
  password varchar(20),
  primary key(id)
);
create table user_infor
(
  id varchar(32) not null,
  user_id varchar(32),
  name varchar(20),
  email varchar(30),  
  sex char,
  age int,
  address varchar(300),
  primary key(id)
);
ALTER TABLE user_infor
    ADD FOREIGN KEY(user_id) 
    REFERENCES user(id)
    ON DELETE CASCADE;
</pre><br />由于没有包含全部的Jar文件，所以朋友需要把上面所述的Jar加载。
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/231797#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 23 Aug 2008 09:51:03 +0800</pubDate>
        <link>http://www.javaeye.com/topic/231797</link>
        <guid>http://www.javaeye.com/topic/231797</guid>
      </item>
      <item>
        <title>Hibernate的事件和拦截器体系</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://betafox.javaeye.com">betafox</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233957" style="color:red;">http://www.javaeye.com/topic/233957</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="Section1" style="layout-grid: 15.6pt none;">
<p class="MsoNormal" align="center" style="line-height: 150%; text-align: center;">&nbsp;</p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">持久层框架底层的拦截器机制是对诸如</span><span lang="EN-US" style="line-height: 150%;">Spring</span><span style="line-height: 150%; font-family: 永中宋体;">等业务管理容器拦截机制的有益补充，使得我们可以在更低层次、更广的对象范围上进行</span><span lang="EN-US" style="line-height: 150%;">AOP</span><span style="line-height: 150%; font-family: 永中宋体;">操作（</span><span lang="EN-US" style="line-height: 150%;">Spring</span><span style="line-height: 150%; font-family: 永中宋体;">虽然将</span><span lang="EN-US" style="line-height: 150%;">Hibernate</span><span style="line-height: 150%; font-family: 永中宋体;">纳入到其容器管理的范围内，但是并没有途径实现对其实体对象的管理）。这样就允许实现某些通用的功能，以及允许对<span lang="EN-US" style="line-height: 150%;"><span style="font-family: Verdana;">Hibernate</span></span><span style="line-height: 150%; font-family: 永中宋体;">功能进行扩展。</span></span></p>
<ol>
<li>
<div class="MsoNormal" style="margin-left: 0cm; text-indent: 0cm; line-height: 150%;"><span style="text-decoration: underline;"><span style="font-size: 14pt; line-height: 150%; font-family: 永中宋体;">拦截器</span></span><span style="text-decoration: underline;"><span lang="EN-US" style="font-size: 14pt; line-height: 150%;">(Interceptors) </span></span></div>
</li>
</ol>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">Interceptor</span><span style="line-height: 150%; font-family: 永中宋体;">接口提供了从会话</span><span lang="EN-US" style="line-height: 150%;">(session)</span><span style="line-height: 150%; font-family: 永中宋体;">回调</span><span lang="EN-US" style="line-height: 150%;">(callback)</span><span style="line-height: 150%; font-family: 永中宋体;">应用程序</span><span lang="EN-US" style="line-height: 150%;">(application)</span><span style="line-height: 150%; font-family: 永中宋体;">的机制，</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">这种回调机制可以允许应用程序在持久化对象被保存、更新、删除或是加载之前，检查并（或）修改其</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">属性。</span><span lang="EN-US" style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="margin-left: 21.25pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">你可以直接实现</span><span lang="EN-US" style="line-height: 150%;">Interceptor</span><span style="line-height: 150%; font-family: 永中宋体;">接口，也可以（最好）继承自</span><span lang="EN-US" style="line-height: 150%;">EmptyInterceptor</span><span style="line-height: 150%; font-family: 永中宋体;">。</span></p>
<p class="MsoNormal" style="margin-left: 21.25pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">拦截器可以有两种</span><span lang="EN-US" style="line-height: 150%;">:Session</span><span style="line-height: 150%; font-family: 永中宋体;">范围内的，和</span><span lang="EN-US" style="line-height: 150%;">SessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">范围内的：</span></p>
<p class="MsoNormal" style="margin-left: 42pt; text-indent: -21pt; line-height: 150%;"><span style="line-height: 150%; font-family: Wingdings;">l<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="line-height: 150%; font-family: 永中宋体;">当使用某个重载的</span><span lang="EN-US" style="line-height: 150%;">SessionFactory.openSession()</span><span style="line-height: 150%; font-family: 永中宋体;">使用</span><span lang="EN-US" style="line-height: 150%;">Interceptor</span><span style="line-height: 150%; font-family: 永中宋体;">作为参数调用打开一个</span><span lang="EN-US" style="line-height: 150%;">session</span><span style="line-height: 150%; font-family: 永中宋体;">的时候，就指定了</span><span lang="EN-US" style="line-height: 150%;">Session</span><span style="line-height: 150%; font-family: 永中宋体;">范围内的拦截器。</span><span lang="EN-US" style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="margin-left: 21pt; text-indent: 21pt; line-height: 150%;"><span lang="EN-US" style="background: #d9d9d9; line-height: 150%; border: black 1pt solid; padding: 0cm;">Session session = sf.openSession( new AuditInterceptor() );</span></p>
<p class="MsoNormal" style="margin-left: 42pt; text-indent: -21pt; line-height: 150%;"><span style="line-height: 150%; font-family: Wingdings;">l<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US" style="line-height: 150%;">SessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">范围内的拦截器要通过</span><span lang="EN-US" style="line-height: 150%;">Configuration</span><span style="line-height: 150%; font-family: 永中宋体;">中注册，而这必须在创建</span><span lang="EN-US" style="line-height: 150%;">SessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">之前。在这种情况下，给出的拦截器会被这个</span><span lang="EN-US" style="line-height: 150%;">SessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">所打开的所有</span><span lang="EN-US" style="line-height: 150%;">session</span><span style="line-height: 150%; font-family: 永中宋体;">使用了，除非</span><span lang="EN-US" style="line-height: 150%;">session</span><span style="line-height: 150%; font-family: 永中宋体;">打开时明确指明了使用的拦截器。</span><span lang="EN-US" style="line-height: 150%;">SessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">范围内的拦截器，必须是线程安全的，因为多个</span><span lang="EN-US" style="line-height: 150%;">session</span><span style="line-height: 150%; font-family: 永中宋体;">可能并发使用这个拦截器，要因此小心不要保存与</span><span lang="EN-US" style="line-height: 150%;">session</span><span style="line-height: 150%; font-family: 永中宋体;">相关的状态</span></p>
<p class="MsoNormal" style="margin-left: 21pt; text-indent: 21pt; line-height: 150%;"><span lang="EN-US" style="background: #d9d9d9; line-height: 150%; border: black 1pt solid; padding: 0cm;">new Configuration().setInterceptor( new AuditInterceptor() );</span></p>
<p class="MsoNormal" style="margin-left: 21.25pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">和</span><span lang="EN-US" style="line-height: 150%;">spring</span><span style="line-height: 150%; font-family: 永中宋体;">配合使用时需要配置</span><span lang="EN-US" style="line-height: 150%;">sessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">对象的</span><span lang="EN-US" style="line-height: 150%;">entityInterceptor</span><span style="line-height: 150%; font-family: 永中宋体;">属性：</span></p>
<div style="background: #cccccc; margin-left: 26.25pt; margin-right: 0cm; border: black 1pt solid; padding: 3pt;">
<pre><span style="font-size: 9pt; color: #000000;">  1 <span style="background: #cccccc;">&lt;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080;">property</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000;"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #0000ff;">name=</span></strong><strong><span style="font-size: 9pt; background: #cccccc; color: #008000;">"entityInterceptor"</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000;">&gt;</span></pre>
<p class="MsoNormal" align="left" style="background: #cccccc; margin-left: 0cm; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 2 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">bean</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">class=</span></strong><strong><span style="font-size: 9pt; background: #cccccc; color: #008000; font-family: 'Courier New';">"**.AuditTrailInterceptor"</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">/&gt;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; margin-left: 0cm; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 3 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">bean</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">class=</span></strong><strong><span style="font-size: 9pt; background: #cccccc; color: #008000; font-family: 'Courier New';">"**.AuditTrailInterceptor2"</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">/&gt;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; margin-left: 0cm; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 4 <span style="background: #cccccc;">&nbsp;&lt;/</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">property</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">&gt; </span></p>
</div>
<p class="MsoNormal" style="line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">&nbsp;</span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">例如：</span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">A</span><span style="line-height: 150%; font-family: 永中宋体;">、下面的这个拦截器，会在一个实现了</span><span lang="EN-US" style="line-height: 150%;"> Auditable</span><span style="line-height: 150%; font-family: 永中宋体;">接口的对象被创建时自动地设置</span><span lang="EN-US" style="line-height: 150%;">createTimestamp</span><span style="line-height: 150%; font-family: 永中宋体;">属性，并在实现了</span><span lang="EN-US" style="line-height: 150%;"> Auditable</span><span style="line-height: 150%; font-family: 永中宋体;">接口的对象被更新时，同步更新</span><span lang="EN-US" style="line-height: 150%;">lastUpdateTimestamp</span><span style="line-height: 150%; font-family: 永中宋体;">属性。</span></p>
<div style="background: #cccccc; border: black 1pt solid; padding: 3pt;">
<p class="MsoNormal" align="left" style="background: #cccccc; text-indent: 12pt; text-align: left; padding: 0cm;"><span style="font-size: 12pt; color: #000000; font-family: 'Courier New';">1 </span><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">p</span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">ublic</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">class</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> AuditInterceptor </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">extends</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> EmptyInterceptor {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 2 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 3 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">private</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">int</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">updates;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 4 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">private</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">int</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">creates;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 5 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">private</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">int</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">loads;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 6 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 7 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">public</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">void</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> onDelete(Object entity,</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 8 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serializable id,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp; 9 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[] state,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;10 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] propertyNames,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;11 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type[] types) {</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;12 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #008000; font-family: 'Courier New';">// do nothing</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;13 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;14 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;15 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">public</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">boolean</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> onFlushDirty(Object entity,</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;16 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serializable id,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;17 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[] currentState,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;18 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[] previousState,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;19 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] propertyNames,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;20 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type[] types) {</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;21 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;22 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">if</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (entity </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">instanceof</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> Auditable) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;23 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">updates++</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;24 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">for</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (</span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">int</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> i = </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">0</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">; i &lt; propertyNames.</span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">length;</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> i++) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;25 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">if</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (</span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">"lastUpdateTimestamp"</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">.equals(propertyNames[i])) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;26 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currentState[i] = </span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">new</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><span style="font-size: 9pt; background: #cccccc; color: #008080; font-family: 'Courier New';">Date(</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">);</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;27 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">return</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">true</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;28 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;29 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;30 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;31 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">return</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">false</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;32 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;33 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;34 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">public</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">boolean</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> onLoad(Object entity,</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;35 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serializable id,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;36 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[] state,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;37 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] propertyNames,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;38 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type[] types) {</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;39 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">if</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (entity </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">instanceof</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> Auditable) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;40 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">loads++</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;41 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;42 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">return</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">false</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;43 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;44 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;45 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">public</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">boolean</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> onSave(Object entity,</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;46 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serializable id,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;47 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[] state,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;48 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] propertyNames,</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;49 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type[] types) {</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;50 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;51 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">if</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (entity </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">instanceof</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> Auditable) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;52 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">creates++</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;53 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">for</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (</span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">int</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> i = </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">0</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">; i &lt; propertyNames.</span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">length;</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> i++) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;54 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">if</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (</span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">"createTimestamp"</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">.equals(propertyNames[i])) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;55 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state[i] = </span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">new</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><span style="font-size: 9pt; background: #cccccc; color: #008080; font-family: 'Courier New';">Date(</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">);</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;56 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">return</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">true</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;57 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;58 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;59 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;60 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">return</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">false</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;61 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;62 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;63 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">public</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">void</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> afterTransactionCompletion(Transaction tx) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;64 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><strong><span style="font-size: 9pt; background: #cccccc; color: #000080; font-family: 'Courier New';">if</span></strong><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> (tx.wasCommitted()) {</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;65 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">out.</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">println(</span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">"Creations: "</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> + </span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">creates </span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">+ </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">", Updates: "</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> + </span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">updates+</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">"Loads: "</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';"> + </span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">loads)</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;66 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;67 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">updates </span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">= </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">0</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;68 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">creates </span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">= </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">0</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;69 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: 9pt; background: #cccccc; color: #660e7a; font-family: 'Courier New';">loads </span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">= </span><span style="font-size: 9pt; background: #cccccc; color: #0000ff; font-family: 'Courier New';">0</span><span style="font-size: 9pt; background: #cccccc; color: #000000; font-family: 'Courier New';">;</span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;70 <span style="background: #cccccc;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;71 </span></p>
<p class="MsoNormal" align="left" style="background: #cccccc; text-align: left; padding: 0cm;"><span style="font-size: 9pt; color: #000000; font-family: 'Courier New';">&nbsp;72 <span style="background: #cccccc;">}</span></span></p>
</div>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;">&nbsp;</p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">&nbsp;</span></p>
<p class="MsoNormal" style="margin-left: 0cm; text-indent: 0cm; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">2.<span style="font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="text-decoration: underline;"><span style="font-size: 14pt; line-height: 150%; font-family: 永中宋体;">事件系统</span></span><span style="text-decoration: underline;"><span lang="EN-US" style="font-size: 14pt; line-height: 150%;">(Event system)</span></span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">如果需要响应持久层的某些特殊事件，你也可以使用</span><span lang="EN-US" style="line-height: 150%;">Hibernate3</span><span style="line-height: 150%; font-family: 永中宋体;">的事件框架。</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">该事件系统可以用来替代拦截器，也可以作为拦截器的补充来使用。</span><span style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">基本上，</span><span lang="EN-US" style="line-height: 150%;">Session</span><span style="line-height: 150%; font-family: 永中宋体;">接口的每个方法都有相对应的事件。比如</span><span lang="EN-US" style="line-height: 150%;"> LoadEvent</span><span style="line-height: 150%; font-family: 永中宋体;">，</span><span lang="EN-US" style="line-height: 150%;">FlushEvent</span><span style="line-height: 150%; font-family: 永中宋体;">，等等（可以查阅</span><span lang="EN-US" style="line-height: 150%;">XML</span><span style="line-height: 150%; font-family: 永中宋体;">配置文件</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">的</span><span lang="EN-US" style="line-height: 150%;">DTD</span><span style="line-height: 150%; font-family: 永中宋体;">以及</span><span lang="EN-US" style="line-height: 150%;">org.hibernate.event</span><span style="line-height: 150%; font-family: 永中宋体;">包来获得所有已定义的事件的列表）。</span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">当某个方</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">法被调用时，</span><span lang="EN-US" style="line-height: 150%;">Hibernate Session</span><span style="line-height: 150%; font-family: 永中宋体;">会生成一个相应的事件并激活所有配置好的事件监听器。被监听的方法所做的其实仅仅是激活监听器，&ldquo;实际&rdquo;的工作是由监听器完成的。你可以自由地选择实现一个自己定制的监听器：比如，实现并注册用来处理处理</span><span lang="EN-US" style="line-height: 150%;">LoadEvent</span><span style="line-height: 150%; font-family: 永中宋体;">的</span><span lang="EN-US" style="line-height: 150%;">LoadEventListener</span><span style="line-height: 150%; font-family: 永中宋体;">接口，</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">来处理所有的调用</span><span lang="EN-US" style="line-height: 150%;">Session</span><span style="line-height: 150%; font-family: 永中宋体;">的</span><span lang="EN-US" style="line-height: 150%;">load()</span><span style="line-height: 150%; font-family: 永中宋体;">方法的请求。</span><span style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">监听器在运行时被实例化为单例</span><span lang="EN-US" style="line-height: 150%;">(singleton)</span><span style="line-height: 150%; font-family: 永中宋体;">对象，也就是说，所有同类型的事件的处理共享同一个监听器实例，因此监听器不应该保存任何与请求相关的状态。</span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">用户定制的监听器需要实现相关的事件监听器接口，或者从一个合适的基类继承（甚至是从</span><span lang="EN-US" style="line-height: 150%;">Hibernate</span><span style="line-height: 150%; font-family: 永中宋体;">自带的默认事件监听器类继承，作者已经通过这些类的</span><span lang="EN-US" style="line-height: 150%;">non-final</span><span style="line-height: 150%; font-family: 永中宋体;">定义给予我们这样的暗示和权利了）。</span></p>
<p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">用户定制的监听器可以通过编程使用</span><span lang="EN-US" style="line-height: 150%;">Configuration</span><span style="line-height: 150%; font-family: 永中宋体;">对象</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">来注册，也可以在</span><span lang="EN-US" style="line-height: 150%;">Hibernate</span><span style="line-height: 150%; font-family: 永中宋体;">的</span><span lang="EN-US" style="line-height: 150%;">XML</span><span style="line-height: 150%; font-family: 永中宋体;">格式的配置文件中进行声明（不支持在</span><span lang="EN-US" style="line-height: 150%;">Properties</span><span style="line-height: 150%; font-family: 永中宋体;">格式的配置文件声明监听器）。</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">下面是一个用户定制的加载事件</span><span lang="EN-US" style="line-height: 150%;">(load event)</span><span style="line-height: 150%; font-family: 永中宋体;">的监听器：</span><span style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">public class MyLoadListener implements LoadEventListener {</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp; // this is the single method defined by the LoadEventListener interface</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp; public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType)</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws HibernateException {</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( !MySecurity.isAuthorized( event.getEntityClassName(), event.getEntityId() ) ) {</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw MySecurityException("Unauthorized access");</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp; }</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">}</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="font-family: 永中宋体;">除此之外你还需要修改一处配置，来告诉</span><span lang="EN-US">Hibernate</span><span style="font-family: 永中宋体;">，除了默认的监听器，还要附加选定的监听器。</span> </p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&lt;hibernate-configuration&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp; &lt;session-factory&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;event type="load"&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;listener class="com.eg.MyLoadListener"/&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;listener class="org.hibernate.event.def.DefaultLoadEventListener"/&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/event&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&nbsp;&nbsp;&nbsp; &lt;/session-factory&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">&lt;/hibernate-configuration&gt;</span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">看看用另一种方式，通过编程的方式来注册它。</span><span lang="EN-US" style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">Configuration cfg = new Configuration();</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">LoadEventListener[] stack = { new MyLoadListener(), new DefaultLoadEventListener() };</span></p>
<p class="MsoNormal" style="margin-left: 21pt;"><span style="color: #339966;">cfg.EventListeners().setLoadEventListeners(stack);</span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">&nbsp;</span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">通过在</span><span lang="EN-US" style="line-height: 150%;">XML</span><span style="line-height: 150%; font-family: 永中宋体;">配置文件声明而注册的监听器不能共享实例。如果在多个</span><span lang="EN-US" style="line-height: 150%;">&lt;listener/&gt;</span><span style="line-height: 150%; font-family: 永中宋体;">节点中使用</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">了相同的类的名字，则每一个引用都将会产生一个独立的实例。如果你需要在多个监听器类型之间共享</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">监听器的实例，则你必须使用编程的方式来进行注册。</span><span lang="EN-US" style="line-height: 150%;"> </span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">&nbsp;</span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">为什么我们实现了特定监听器的接口，在注册的时候还要明确指出我们要注册哪个事件的监听器呢？</span><span style="line-height: 150%;"> </span><span style="line-height: 150%; font-family: 永中宋体;">这是因为一个类可能实现多个监听器的接口。在注册的时候明确指定要监听的事件，可以让启用或者禁用对某个事件的监听的配置工作简单些。</span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span lang="EN-US" style="line-height: 150%;">&nbsp;</span></p>
<p class="MsoNormal" style="margin-left: 21pt; line-height: 150%;"><span style="line-height: 150%; font-family: 永中宋体;">当与</span><span lang="EN-US" style="line-height: 150%;">Spring</span><span style="line-height: 150%; font-family: 永中宋体;">配合使用时同样需要配置</span><span lang="EN-US" style="line-height: 150%;">sessionFactory</span><span style="line-height: 150%; font-family: 永中宋体;">的</span><span lang="EN-US" style="line-height: 150%;">eventListener</span><span style="line-height: 150%; font-family: 永中宋体;">属性。</span></p>
</div>
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/233957#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 14:45:17 +0800</pubDate>
        <link>http://www.javaeye.com/topic/233957</link>
        <guid>http://www.javaeye.com/topic/233957</guid>
      </item>
      <item>
        <title>hibernate inverse属性</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://lsk.javaeye.com">lsk</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233953" style="color:red;">http://www.javaeye.com/topic/233953</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          先创造环境..在测试.<br />类如下:<br /><pre name="code" class="java">
Parent类:

private String id;
	private List&lt;Child> children = new ArrayList&lt;Child>();
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public List&lt;Child> getChildren() {
		return children;
	}
	public void setChildren(List&lt;Child> children) {
		this.children = children;
	}
Child类:
private String id;
	private Parent parent;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public Parent getParent() {
		return parent;
	}
	public void setParent(Parent parent) {
		this.parent = parent;
	}

HibernateMapping文件:
&lt;class name="Parent" table="parent">
		&lt;id name="id" column="id" type="java.lang.String"
			unsaved-value="null">
			&lt;generator class="org.hibernate.id.UUIDHexGenerator" />
		&lt;/id>
		&lt;bag name="children" inverse="false" >
			&lt;key column="parent_id" />
			&lt;one-to-many class="Child" />
		&lt;/bag>
	&lt;/class>

	&lt;class name="Child" table="child">
		&lt;id name="id" column="id" type="java.lang.String">
			&lt;generator class="org.hibernate.id.UUIDHexGenerator" />
		&lt;/id>
		&lt;many-to-one name="parent" class="Parent" column="parent_id" />
	&lt;/class>
</pre><br />ok.再来看一下.inverse="true"和"false"两种情况下的insert动作有何不同<br /><pre name="code" class="java">
Parent parent1 = new Parent();
this.cmsManager.save(parent1);
Child child1 = new Child();
//parent1.getChildren().add(child1); <span style="color: red">情况1</span>
//child1.setParent(parent1); <span style="color: red">情况2</span>
this.cmsManager.save(child1);
</pre><br />条件1: 当inverse="false"的时候(也就是由parent来维护二者之间的关系.)<br />下面代码,情况1和情况2都可以以正确的关联关系插入到数据库当中.<br />之所以情况2(child1.setParent)会正确的插入到数据库当中.是因为hibernate把他当作一个单方面的关联来处理的.和inverse无关.<br /><br />条件2:当inverse="true"的时候(也就是说由child来维护二者的关系)<br />下面代码,情况1是不会正确的插入关联关系的.也就是Childe的parentId为null. 如果many-to-one那里设置了not-null="true"会得到一个异常,<br />情况2会正确的插入关联关系.也就是Child的parentId不为null<br /><br />OK,根据上面两个小测试.基本了解inverse的属性到底是个什么意思:<br />对于集合实体映射(也就是集合当中的对象都是需要持久化到数据库当中去的)来说,当inverse="false"的时候.关联关系就交给Parent方来管理.java代码当中涉及到关联关系操作.用parent.getChildren().add()才会使关联关系生效.当inverse="true"的时候.关联关系是交给Child来管理.java代码当中需要利用Child.setParent来控制关联关系.
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/233953#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 14:38:09 +0800</pubDate>
        <link>http://www.javaeye.com/topic/233953</link>
        <guid>http://www.javaeye.com/topic/233953</guid>
      </item>
      <item>
        <title>ImageIO读jpg的时候出现exception：bandOffsets.length is wr</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://cjc19762338.javaeye.com">cjc19762338</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233923" style="color:red;">http://www.javaeye.com/topic/233923</a>&nbsp;
          发表时间: 2008年08月28日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          用java处理图片的时候，ImageIO读jpg的时候出现exception：bandOffsets.length is wrong。我也遇到过，最终也解决啦，把成果跟大家分享。<br /><br />原因可能是JPEG图片的ICC信息可能已经被破坏了，所以ImageIO会抛出异常<br /><br />解决办法：<br /><br />BufferedImage bis = null;<br />   try{<br />       bis = ImageIO.read(file);<br />       bis.getWidth();<br />       bis.getHeight();<br />   }catch(Exception e){<br />    try<br />    {<br />     ThumbnailConvert tc = new ThumbnailConvert();<br />     tc.setCMYK_COMMAND(file.getPath());<br />     Image image =null;<br />     image = Toolkit.getDefaultToolkit().getImage(file.getPath());<br />       MediaTracker mediaTracker = new MediaTracker(new Container());<br />     mediaTracker.addImage(image, 0);<br />     mediaTracker.waitForID(0);<br />      image.getWidth(null);<br />     image.getHeight(null);<br />    }catch (Exception e1){<br />     e1.printStackTrace();<br />    }<br />   }<br /><br />这两句代码，是处理cmyk类型的图片，需要ImageMagick的支持<br /><br />ThumbnailConvert tc = new ThumbnailConvert();<br />     tc.setCMYK_COMMAND(file.getPath());//用于把cmyk转成rgb<br /><br />ImageMagick的具体指令是：mogrify -colorspace RGB -quality 100 file1
          <br/>
          <span style="color:red;">
            <a href="http://dlee.javaeye.com/topic/233923#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></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 28 Aug 2008 13:51:21 +0800</pubDate>
        <link>http://www.javaeye.com/topic/233923</link>
        <guid>http://www.javaeye.com/topic/233923</guid>
      </item>
      <item>
        <title>工厂模式运用-锻造武器</title>
        <author>JavaEye网站</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://everlive.javaeye.com">40020072</a>&nbsp;
          链接：<a href="http://www.javaeye.com/topic/233420" style="color:red;">http://www.javaeye.com/topic/233420</a>&nbsp;
          发表时间: 2008年08月27日
          <br/>
          声明：本文系JavaEye网站发布的原创文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="color: #003366;"><span style="color: #003366;"><strong>目标</strong></span>：使用一些材料，在一座城市打造出一把武器</span></p>
<p>&nbsp;</p>
<p><span style="color: #003366;"><span style="color: #003366;"><strong>包含元素</strong></span>：</span></p>
<p><span style="color: #003366;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一、锻造材料：</span></p>
<p><span style="color: #003366;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、 源生材料:&nbsp;</span><span style="color: #008000;"> <span style="color: #008000;">源生火焰<img src="http://www.javaeye.com/upload/picture/pic/20685/6c7e1cd2-3952-3574-828a-869c9af9e720-thumb.jpg?1219827073" height="37" alt="" width="38" />&nbsp;&nbsp; 源生空气<img src="http://www.javaeye.com/upload/picture/pic/20691/736c8b84-61c7-30d7-923b-b260b0fbcf96-thumb.jpg?1219827159" height="37" alt="" width="39" />&nbsp;&nbsp; 源生法力<img src="http://www.javaeye.com/upload/picture/pic/20693/ead69ef6-8121-3941-8d61-ae4421ae03a4-thumb.jpg?1219827230" height="37" alt="" width="38" />&nbsp;&nbsp;&nbsp; 源生之土<img src="http://www.javaeye.com/upload/picture/pic/20695/cd5d6a83-1a38-30b1-aed8-d055fa614fdd-thumb.jpg?1219827344" height="37" alt="" width="38" /></span></span></p>
<p><span style="color: #003366;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、 矿石：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">氪金锭&nbsp;&nb