webber

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  11 Posts :: 2 Stories :: 3 Comments :: 0 Trackbacks

2010年3月15日 #

在Java的世界里,无论类还是各种数据,其结构的处理是整个程序的逻辑以及性能的关键。由于本人接触了一个有关性能与逻辑同时并存的问题,于是就开始研究这方面的问题。找遍了大大小小的论坛,也把《Java 虚拟机规范》,《apress,.java.collections.(2001),.bm.ocr.6.0.shareconnector》,和《Thinking in Java》翻了也找不到很好的答案,于是一气之下把JDK的 src 解压出来研究,扩然开朗,遂写此文,跟大家分享感受和顺便验证我理解还有没有漏洞。 这里就拿HashMap来研究吧。



  HashMap可谓JDK的一大实用工具,把各个Object映射起来,实现了“键--值”对应的快速存取。但实际里面做了些什么呢?

  在这之前,先介绍一下负载因子和容量的属性。大家都知道其实一个 HashMap 的实际容量就 因子*容量,其默认值是 16×0.75=12; 这个很重要,对效率很一定影响!当存入HashMap的对象超过这个容量时,HashMap 就会重新构造存取表。这就是一个大问题,我后面慢慢介绍,反正,如果你已经知道你大概要存放多少个对象,最好设为该实际容量的能接受的数字。

  两个关键的方法,put和get:

  先有这样一个概念,HashMap是声明了 Map,Cloneable, Serializable 接口,和继承了 AbstractMap 类,里面的 Iterator 其实主要都是其内部类HashIterator 和其他几个 iterator 类实现,当然还有一个很重要的继承了Map.Entry 的 Entry 内部类,由于大家都有源代码,大家有兴趣可以看看这部分,我主要想说明的是 Entry 内部类。它包含了hash,value,key 和next 这四个属性,很重要。put的源码如下

public Object put(Object key, Object value) {
Object k = maskNull(key);

  这个就是判断键值是否为空,并不很深奥,其实如果为空,它会返回一个static Object 作为键值,这就是为什么HashMap允许空键值的原因。

int hash = hash(k);
int i = indexFor(hash, table.length);

  这连续的两步就是 HashMap 最牛的地方!研究完我都汗颜了,其中 hash 就是通过 key 这个Object的 hashcode 进行 hash,然后通过 indexFor 获得在Object table的索引值。

  table???不要惊讶,其实HashMap也神不到哪里去,它就是用 table 来放的。最牛的就是用 hash 能正确的返回索引。其中的hash算法,我跟JDK的作者 Doug 联系过,他建议我看看《The art of programing vol3》可恨的是,我之前就一直在找,我都找不到,他这样一提,我就更加急了,可惜口袋空空啊!!!

  不知道大家有没有留意 put 其实是一个有返回的方法,它会把相同键值的 put 覆盖掉并返回旧的值!如下方法彻底说明了 HashMap 的结构,其实就是一个表加上在相应位置的Entry的链表:

for (Entry e = table[i]; e != null; e = e.next) {
 if (e.hash == hash && eq(k, e.key)) {
  Object oldvalue = e.value;
  e.value = value; //把新的值赋予给对应键值。
  e.recordAccess(this); //空方法,留待实现
  return oldvalue; //返回相同键值的对应的旧的值。
 }
}
modCount++; //结构性更改的次数
addEntry(hash, k, value, i); //添加新元素,关键所在!
return null; //没有相同的键值返回
}

  我们把关键的方法拿出来分析:

void addEntry(int hash, Object key, Object value, int bucketIndex) {
table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]);

  因为 hash 的算法有可能令不同的键值有相同的hash码并有相同的table索引,如:key=“33”和key=Object g的hash都是-8901334,那它经过indexfor之后的索引一定都为i,这样在new的时候这个Entry的next就会指向这个原本的table[i],再有下一个也如此,形成一个链表,和put的循环对定e.next获得旧的值。到这里,HashMap的结构,大家也十分明白了吧?

if (size++ >= threshold) //这个threshold就是能实际容纳的量
resize(2 * table.length); //超出这个容量就会将Object table重构

  所谓的重构也不神,就是建一个两倍大的table(我在别的论坛上看到有人说是两倍加1,把我骗了),然后再一个个indexfor进去!注意!!这就是效率!!如果你能让你的HashMap不需要重构那么多次,效率会大大提高!

  说到这里也差不多了,get比put简单得多,大家,了解put,get也差不了多少了。对于collections我是认为,它是适合广泛的,当不完全适合特有的,如果大家的程序需要特殊的用途,自己写吧,其实很简单。(作者是这样跟我说的,他还建议我用LinkedHashMap,我看了源码以后发现,LinkHashMap其实就是继承HashMap的,然后override相应的方法,有兴趣的同人,自己looklook)建个 Object table,写相应的算法,就ok啦。

  举个例子吧,像 Vector,list 啊什么的其实都很简单,最多就多了的同步的声明,其实如果要实现像Vector那种,插入,删除不多的,可以用一个Object table来实现,按索引存取,添加等。

  如果插入,删除比较多的,可以建两个Object table,然后每个元素用含有next结构的,一个table,如果要插入到i,但是i已经有元素,用next连起来,然后size++,并在另一个table记录其位置

HashMap用法

 

 

package hashmap;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

public class HashMap1 {
//初始化
private void init(Map map,String kind)
{
   if(map != null)
   {
    for(int i=1; i<6; i++)
    {
     map.put(String.valueOf(i),kind+i);
    }
   }
}

//结果输出
private void outPut(Map map)
{
   if(map != null)
   {
    Object key    = null;
    Object value = null;
    Iterator iterater = map.keySet().iterator();
    while(iterater.hasNext())
    {
     key = iterater.next();
     value = map.get(key);
     System.out.print(key+": "+value+"\t");
    }
    System.out.println("\n");
   }
}
public static void main(String args[])
{
    HashMap hashmap = new HashMap();
    hashmap.put("x", "1");
    hashmap.put("u", "2");
    hashmap.put("z", "3");
    hashmap.put("h", "4");
    hashmap.put("a", "5");
    hashmap.put("o", "6");
    hashmap.put("g", "7");
    hashmap.put("u", "8");
    hashmap.put("a", "9");
    hashmap.put("n", "10");
    hashmap.put("g", "11");

     Object key    = null;
     Object value = null;
     Iterator iterater = hashmap.keySet().iterator();
     while(iterater.hasNext())
     {
      key = iterater.next();
      value = hashmap.get(key);
      System.out.print(key+": "+value+"\t");
     }
     System.out.println("\n");

}
//声明HashMap对象
private void setHashMap()
{
   HashMap hashMap = new HashMap();
   init(hashMap,"HashMap");
   hashMap.put(null,"键值为空");
   hashMap.put("值为空",null);
   System.out.println("这是HashMap对象的键与值:");
   outPut(hashMap);
}
     //声明Hashtable对象
private void setHashtable(){
   Hashtable hashtable = new Hashtable();
   init(hashtable,"Hashtable");
   //hashtable.put(null,"键值为空"); Hashtable不允许键或值为null;
   //hashtable.put("值为空",null);
   System.out.println("这是Hashtable对象的键与值:");
   outPut(hashtable);
}
     //声明LinkedHashMap对象
private void setLinkedHashMap(){
   LinkedHashMap linkedHashMap = new LinkedHashMap();
   init(linkedHashMap,"LinkedHashMap");
   linkedHashMap.put(null,"键值为空");
   linkedHashMap.put("值为空",null);
   System.out.println("这是LinkedHashMap对象的键与值:");
   outPut(linkedHashMap);
}
     //声明TreeMap对象
private void setTreeMap(){
   TreeMap treeMap = new TreeMap();
   //TreeMap treeMap = new TreeMap(new MySort());//按自定义的方式排序
   init(treeMap,"TreeMap");
   treeMap.put("0", "后插入的值");
   //treeMap.put(null,"键值为空"); TreeMap不允许键或值为null
   //treeMap.put("值为空",null);
   System.out.println("这是TreeMap对象的键与值:");
   outPut(treeMap);
}
// public static void main(String[] args){
//   HashMapDemo tm = new HashMapDemo();
//   tm.setHashMap();
//   tm.setHashtable();
//   tm.setLinkedHashMap();
//   tm.setTreeMap();
//
//   Map hashMap = new HashMap();
//   hashMap.put(null, "键值为null");
//   hashMap.put("值为null", null);
//   System.out.println("新建HashMap对象元素的记录数是:"+hashMap.size());
//   hashMap.remove(null);
//   System.out.println("删除键值为null的HashMap对象元素的记录数是:"+hashMap.size());
// }

posted @ 2010-03-26 17:08 webber 阅读(590) | 评论 (0)编辑 收藏

 

第一种:
Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry entry = (Map.Entry) iter.next();
    Object key = entry.getKey();
    Object val = entry.getValue();
}
效率高,以后一定要使用此种方式!
                                                                                    
第二种:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
    Object key = iter.next();
    Object val = map.get(key);
}
效率低,以后尽量少使用!
HashMap的遍历有两种常用的方法,那就是使用keyset及entryset来进行遍历,但两者的遍历速度是有差别的,下面请看实例:
import java.util.*;
            public class HashMapTest {
            public static void main(String[] args) {
            HashMap< Integer,String> hashmap = new HashMap< Integer,String>();
            for (int i = 0; i <1000; i++ ) {
            hashmap.put(i, "thanks");
            }
            long bs = Calendar.getInstance().getTimeInMillis();
            Iterator iterator = hashmap.keySet().iterator();
            while (iterator.hasNext()) {
            System.out.print(hashmap.get(iterator.next()));
            }
            System.out.println();
            System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
            listHashMap();
            }
            public static void listHashMap() {
            java.util.HashMap< Integer,String> hashmap = new java.util.HashMap< Integer,String>();
            for (int i = 0; i < 1000; i++ ) {
            hashmap.put(i, "thanks");
            }
            long bs = Calendar.getInstance().getTimeInMillis();
            Iterator< Map.Entry< Integer,String>> it = hashmap.entrySet().iterator();
            while (it.hasNext()) {
            Map.Entry< Integer,String> entry = it.next();
            // entry.getKey() 返回与此项对应的键
            // entry.getValue() 返回与此项对应的值
            System.out.print(entry.getValue());
            }
            System.out.println();
            System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
            } 

对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。而entryset只是遍历了第一次,他把key和value都放到了entry中,所以就快了。

注:Hashtable的遍历方法和以上的差不多!

posted @ 2010-03-26 16:57 webber 阅读(222) | 评论 (0)编辑 收藏

web.xml  
// 这里不需要配置字符过滤,网上有的例子加了,实际上
webwork.properties里设置如下就可以了页面也是GBK
webwork.locale=zh_CN
webwork.i18n.encoding=GBK
---------------------------
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

     <context-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
     </context-param>

<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
   <listener-class>com.atlassian.xwork.ext.ResolverSetupServletContextListener</listener-class>
</listener>
     <!--
     <servlet>
     <servlet-name>context</servlet-name>
              <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
      </servlet>
      -->
     <servlet>
         <servlet-name>webwork</servlet-name>
         <servlet-class>com.opensymphony.webwork.dispatcher.ServletDispatcher</servlet-class>
         <load-on-startup>3</load-on-startup>
     </servlet>

<servlet>
   <servlet-name>freemarker</servlet-name>
   <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class>
   <load-on-startup>10</load-on-startup>
</servlet>

     <servlet-mapping>
         <servlet-name>webwork</servlet-name>
         <url-pattern>*.action</url-pattern>
     </servlet-mapping>

<servlet-mapping>
   <servlet-name>freemarker</servlet-name>
   <url-pattern>*.ftl</url-pattern>
</servlet-mapping>

     <welcome-file-list>
         <welcome-file>index.html</welcome-file>
     </welcome-file-list>

     <taglib>
         <taglib-uri>webwork</taglib-uri>
         <taglib-location>/WEB-INF/webwork.tld</taglib-location>
     </taglib>

</web-app>

---------------------------

xwork.xml

==================---------------------------------------------
<?xml version="1.0"?>
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>

   <include file="webwork-default.xml"/>
     <package name="users" extends="webwork-default"
         externalReferenceResolver="com.atlassian.xwork.ext.SpringServletContextReferenceResolver">

         <interceptors>
             <interceptor name="reference-resolver" class="com.opensymphony.xwork.interceptor.ExternalReferencesInterceptor"/>
             <interceptor-stack name="myDefaultWebStack">
                 <interceptor-ref name="defaultStack"/>
                 <interceptor-ref name="reference-resolver"/>
                 <interceptor-ref name="model-driven"/>
        <interceptor-ref name="params"/>
             </interceptor-stack>
         </interceptors>

<default-interceptor-ref name="myDefaultWebStack"/>
         <action name="blogUser" class="com.jsblog.action.BlogUserAction">
    <external-ref name="baseDao">baseDaoTarget</external-ref>      //这里是把applicationContext里配置的DAO 注入action里 action里要有baseDao属性
    <result name="success">/add.htm</result>
   </action>
-------------------------------------------------------------------------

applicationContext.xml

---------------------------------------------------------------------------
<?xml version="1.0"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="no" default-dependency-check="none" default-lazy-init="false">
     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
         <property name="driverClassName">
             <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
         </property>
         <property name="url">
             <value>jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=jsblog;SelectMethod=cursor</value>
         </property>
         <property name="username">
             <value>sa</value>
         </property>
         <property name="password">
             <value>jfy</value>
         </property>
     </bean>

     <bean id="sessionFactory"
           class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
         <property name="dataSource">
             <ref local="dataSource"/>
         </property>
         <property name="mappingResources">
             <list>
                 <value>com/jsblog/BlogUserForm.hbm.xml</value>
             </list>
         </property>
         <property name="hibernateProperties">
             <props>
                 <prop key="hibernate.dialect">
                     net.sf.hibernate.dialect.SQLServerDialect
                 </prop>
                 <prop key="hibernate.show_sql">true</prop>
             </props>
         </property>
     </bean>

     <bean id="transactionManager"
           class="org.springframework.orm.hibernate.HibernateTransactionManager">
         <property name="sessionFactory">
             <ref local="sessionFactory"/>
         </property>
     </bean>


     <bean id="baseDaoTarget" class="com.jsblog.dao.BlogUserDao">
         <property name="sessionFactory">
             <ref local="sessionFactory"/>
         </property>
     </bean>


</beans>
---------------------------------------------------------------------------

BlogUserDao.java
---------------------------------------------------------------------------
package com.jsblog.dao;

import org.springframework.orm.hibernate.support.HibernateDaoSupport;
import org.springframework.orm.hibernate.HibernateCallback;
import org.springframework.orm.hibernate.SessionFactoryUtils;
import com.jsblog.BlogUserForm;

import java.io.Serializable;
import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;

public class BlogUserDao extends HibernateDaoSupport implements BaseDao {

     public void insert(BlogUserForm bloguser) {
         getHibernateTemplate().save(bloguser);
     }

}

posted @ 2010-03-15 10:10 webber 阅读(1053) | 评论 (0)编辑 收藏

 

基于webwork spring hibernate 项目的开发
这三者的结合,应该是java web编程最好的模式。

首先说明三者各自负责的职务:

1 hibernate 负责数据库的操作

2 spring 负责真正的业务操作

3 webwork 负责请求转交,并把spring的处理结果返回给用户


以往的开发中,很多人注重MVC模式。的确,这种模式把程序以面向对象的思想分成 了三个部分。但在web开发中,并不能单纯的运用此种模式:web开发的View是固定的(页面),而在引入hibernate后,model这一块也非常简单和清晰。就剩下control了,这是web开发的关键部分,现在流行的做法便是将control细分成两个部分:dispacher(转交器)和business object(处理业务逻辑的对象)。并将后者抽出接口,甚至和model共享接口,一边真正做到对dispacher隐藏逻辑实现。

而这种M-V-D-B(model-view-dispacher-business object)模式的实现有好多方式。比如一个bo(business object)对象的创建,你可以直接 new,也可以动态加载,采用工厂方法,抽象工厂。但最好的就是用spring容器。dispacher只管用接口就行了,具体类已经有spring的 AOP给注入了。

当然spring也可以很好地和hibernate结合,你可以采用DAO,也可以用spring的hibernate 模板。但这都不重要,因为你的业务对象已经和调用层彻底分开了,当业务层需要和hibernate打交道的时候,直接做个HibernateUtil也未尝不可呀。怎么做都已经不是关键。

下面就具体介绍spring webwork的结合方式。

在webwork 中的wiki doc中有三种结合方式(google查),我这里采用的最后一种--采用一个自动装配的拦截器com.opensymphony.xwork.spring.interceptor.ActionAutowiringInterceptor关键代码如下:


   ApplicationContext applicationContext = (ApplicationContext)ActionContext.getContext().getApplication().get(
          WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        factory = new SpringObjectFactory();
        factory.setApplicationContext(getApplicationContext());
    Action bean = invocation.getAction();
    factory.autoWireBean(bean);
   
    ActionContext.getContext().put(APPLICATION_CONTEXT, context);

1、webwork、spring的集成
  (1)、开启spring的集成:
         首先将最新的spring的jar加到classpath中,然后在src目录下建立webwork.properties文件,文件只包含下面的内容
        webwork.objectFactory=spring
         这种情况下,所有的对象都至少会试图使用Spring来创建.如果它们不能被Spring创建,然后WebWork会自己创建对象.接下来,在
        web.xml打开Spring的Listener
           <listener>
             <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
           </listener>
        由于使用标准的Listener来集成Spring,它可以被配置来支持除了applicationContext.xml之外的配置文件.把下面的几行添加到
       web.xml会让Spring的ApplicationContext从所有匹配给定的规则的文件中初始化:

       <!-- Context Configuration locations for Spring XML files -->
        <context-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext   
       </context-param>
       根据需要配置相应的spring上下文文。
   (2)、在spring中初始化Action
         正常情况下,在xwork.xml里可以为每个action指定类.当你使用SpringObjectFactory时WebWork会请求Spring来
         创建action并按照缺省指定的自动装配行为来装配依赖的组件.SpringObjectFactory 也会设置所有的bean的后置处理程序
        (post processors)来完成类似对Action进行事务,安全等等方面的代理的事情.Spring可以不依赖外在的配置来自动确定.
         对于大多数的使用,这就是全部需要的了,用来配置action,设置它们获取服务和依赖组件.
         强烈推荐使用一种声明式的方法来让Spring知道为action提供什么.这包括让bean能够自动装配,无论是把Action里的
         依赖的属性命名为和Spring应该提供的Bean的名字一致(这允许基于名字的自动装配),或者使用by type方式的自动装配,也就是在注册到
        Spring的Bean中需要的类型仅拥有一个.也可以包括使用JDK5的标准来声明事务和安全需求,而不是必须在你的Spring配置里明确设置代理.
         如果能找到方法让Spring在没有任何明确的配置(在_applicationContext.xml_中)的情况下知道需要为action做什么,那么就不
         需要在两个地方维护这个配置了.
         当然,有时候可能想要Spring完全来管理bean.这是有实际意义的,例如,如果想要为bean设置更复杂的AOP或者Spring相关的技术,
         例如Acegi.为了达到这个目的,所有必须要做的事情就是在Spring的 applicationContext.xml 里配置bean,然后在 xwork.xml
         里改变你的WebWork action的类属性来使用在Spring里面定义的bean的名字,而不再使用类名. 
        xwork.xml文件也会改变action类的属性,最后留下的就像这样    
         
        <xwork>
       <!-- Include webwork defaults (from WebWork JAR). -->
         <include file="webwork-default.xml" />

       <!-- Configuration for the default package. -->
         <package name="default" extends="webwork-default">
           <action name="register" class="userAction" method="register">
              <result name="success">/pages/registerSuccess.jsp</result>
           </action>
         </package>
       </xwork>
        在applicationContext.xml 里定义了一个名字为 "userAction"的Spring的bean.注意cn.com.nawang.Action.UserAction不需要
        改变,因为它可能是自动装配的:
        <bean id="userAction" class="cn.com.nawang.action.UserAction" > 
             <property name="userService" ref="userService"/>
        </bean>
       注:bean中的id值必须与xwork.xml中对应的class值一致。
        
   2、 基于Hibernate3的原生API实现DAO
        Hibernate 3.0.1引入了一个新的特性:“带上下文环境的Session”。 这一特性使得Hibernate自身具备了每个事务绑定当前 Session 对象的功能。
         这与Spring中每个Hibernate的 Session 与事务同步的功能大致相同。
   (1)、 为Dao创建基类BaseDao
         public class BaseDao {
         private SessionFactory  sessionFactory;

         public void setSessionFactory(SessionFactory sessionFactory) {
          this.sessionFactory = sessionFactory;
         }
 
         public Session getSession(){
                 Session session = this.sessionFactory.getCurrentSession();
                 return session;
         }
         }
   (2)、在子类Dao中实现具体持久化操作
        public class UserDao extends BaseDao implements IUserDao {
        public void saveUser(User user) throws HibernateException {
              getSession().save(user);
        }     
        }
   (3)、在上下文中配置
        <bean id="baseDao" class="cn.com.nawang.dao.BaseDao">
           <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
    
        <bean id="userDao" class="cn.com.nawang.dao.impl.UserDao" parent="baseDao"/>
       
        <bean id="userService" class="cn.com.nawang.service.impl.UserService">
           <property name="userDao" ref="userDao"/>
        </bean>
   
        <bean id="userAction" class="cn.com.nawang.action.UserAction" > 
          <property name="userService" ref="userService"/>
        </bean>    
     重启服务,在web页面上触发register的action,执行后,抛出下面的异常:
      Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    google了下,大概明白了是因为没有配置了事务导致的错误。在配置事务之前,查看了以前的一个采用HibernateDaoSupport实现的项目,记得
     当时并不需要配置事务就可以正常运行。于是,让UserDao继承于HibernateDaoSupport,修改后的代码如下:
         public class UserDao extends BaseDao implements IUserDao {
        public void saveUser(User user) throws HibernateException {
              getHibernateTemplate().save(user);
        }     
        }
     接下去,修改spring上下文中的相关配置,
       <!--
        <bean id="baseDao" class="cn.com.nawang.dao.BaseDao">
           <property name="sessionFactory" ref="sessionFactory"/>
        </bean>-->
    
        <bean id="userDao" class="cn.com.nawang.dao.impl.UserDao">
           <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
       
        <bean id="userService" class="cn.com.nawang.service.impl.UserService">
           <property name="userDao" ref="userDao"/>
        </bean>
   
        <bean id="userAction" class="cn.com.nawang.action.UserAction" > 
          <property name="userService" ref="userService"/>
        </bean> 
     保存修改后的,重启服务,再次触发register的action,用户信息成功保存。
    
     去掉HibernateDaoSupport的dao实现后,又换回基于hibernate3.0原生API的实现方式,根据之前google后的结果,给userService配置
     事务,拷贝了下之前项目中的配置,并做相应修改,修改后的内容如下:
       <bean id="baseTransaction"
       class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="proxyTargetClass" value="true"/>
        <property name="transactionAttributes">
           <props>                
               <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
               <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
               <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>                
               <prop key="save*">PROPAGATION_REQUIRED</prop>                
               <prop key="add*">PROPAGATION_REQUIRED</prop>                
               <prop key="update*">PROPAGATION_REQUIRED</prop>                
               <prop key="delete*">PROPAGATION_REQUIRED</prop>            
           </props>       
        </property>  
    </bean>
   
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>      
   
    <bean id="baseDao" class="cn.com.nawang.dao.BaseDao">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    <bean id="userDao" class="cn.com.nawang.dao.impl.UserDao" parent="baseDao"/>
   
    <bean id="userServiceTarget" class="cn.com.nawang.service.impl.UserService">
       <property name="userDao" ref="userDao"/>
    </bean>
   
    <bean id="userService" parent="baseTransaction">
       <property name="target" ref="userServiceTarget"/>
    </bean>
   
    <bean id="userAction" class="cn.com.nawang.action.UserAction" > 
       <property name="userService" ref="userService"/>
    </bean>
   
    保存修改内容,重启服务,重启中出现错误,查看了spring in action中的相关配置,发现baseTransaction这个bean的配置稍有不同,
    上面那个配置是参考springside的,当时那个项目赶,就直接拿过来用,也没出现问题,就不认真去考虑,现在拷贝到现有项目中,却出错了,
    于是先根据书上的介绍做相应修改,改后的内容如下:
       <bean id="baseTransaction"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true">
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
           <props>                
               <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
               <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
               <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>                
               <prop key="save*">PROPAGATION_REQUIRED</prop>                              
               <prop key="update*">PROPAGATION_REQUIRED</prop>                
               <prop key="delete*">PROPAGATION_REQUIRED</prop>            
           </props>       
        </property>  
    </bean>
    去掉了<property name="proxyTargetClass" value="true"/>的配置,将abstract="true"改为lazy-init="true",保存修改
    重启服务,并再次触发register的action,一切如所愿。 

posted @ 2010-03-15 10:00 webber 阅读(713) | 评论 (0)编辑 收藏