本文在060216进行了修改,因为发现了测试中的错误!注意5.5和7的内容。
1、引子:其实是ajoo的这篇“Nuts和Spring 1.2.6 效率对比”和“IoC容器的prototype性能测试 ”,他们在Javaeye上详细讨论了Spring的prototype的缺陷。Spring的prototype指的就是singleton="false"的bean,具体可以看Spring参考手册“3.2.5. To singleton or not to singleton”介绍。

2、Webwork 2.2的Spring结合问题:Webwork 2.2已经抛弃自己的IoC,默认使用Spring的IoC。上在OpenSymphony的官方Wiki,和jscud后来的几篇文章中没有特别提出prototype的问题。但是托他们的福,我们已经顺利的使Spring和Webwork良好的协同工作起来了。可是而后的一些问题却把prototype的问题搞得神秘起来……ajoo的测试中指出Spring的prototype性能很差,参见后面参考中的一篇文章和Javaeye的讨论。而后又发现robbin在Javaeye的Wiki上面的“集成webwork和spring”中的最后注到:“注意:目前并不推荐使用Spring来管理Webwork Action,因为对于prototype类型的bean来说,Spring创建bean和调用bean的效率是很低的!更进一步信息请看IoC容器的prototype性能测试”这就使我们常用的Spring+Webwork2.2的连接中使用的prototype的问题被摆出来了。我现在的项目中使用了prototype的方式将Webwork Action使用Spring进行显示的装配,我担心这个性能的问题会很严重,所以今天花了半天时间具体测试了一下。

3、Prototype VS autowire的解释:我不知道怎么命名两种方式好,所以这里先做个解释:spring的配置中Action会有个id,如:
<bean id="someAction" class="com.tin.action.SomeAction" parent="basicActionWithAuthtication" singleton="false"> <property name="someDAO"> <ref bean="someDAO" /> </property></bean>

我指的prototype方式就是在xwork中这样配置:
<action name="someAction" class="someAction">

而autowire方式就是指在xwork中这样配置:
<action name="someAction" class="com.tin.action.SomeAction">

看起来相同,但其实不同(我以前发过帖子,其中说这几种方法都可,但是其实它们的机制是不同的。

4、Portotye和autowire在XWork的SpringObjectFactory中是如何运作的:我们先看一下代码,就能明白两者的区别了:
public Object buildBean(String beanName, Map extraContext) throws Exception { try { return appContext.getBean(beanName);        } catch (NoSuchBeanDefinitionException e) {            Class beanClazz = getClassInstance(beanName); return buildBean(beanClazz, extraContext);        }    } public Object buildBean(Class clazz, Map extraContext) throws Exception {        Object bean; try {            bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);        } catch (UnsatisfiedDependencyException e) { // Fall back            bean = super.buildBean(clazz, extraContext);        }        bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName()); // We don’t need to call the init-method since one won’t be registered.        bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName()); return autoWireBean(bean, autoWiringFactory);    } public Object autoWireBean(Object bean) { return autoWireBean(bean, autoWiringFactory);    }

如果按照autowire配置会使用第二个buildBean方法,而prototype会使用第一个buildBean方法。

5、我的测试,首先测试SpringObjectFactory的理论效率:
public class testSpringObjectFactory extends TestCase { protected FileSystemXmlApplicationContext appContext; protected SpringObjectFactory sof = null; protected Map map = null; final String[] paths = { "WebRoot/WEB-INF/applicationContext.xml", "WebRoot/WEB-INF/spring-daos.xml", "WebRoot/WEB-INF/spring-actions.xml"        }; protected void setUp() throws Exception { super.setUp();        appContext = new FileSystemXmlApplicationContext(paths);        sof = new SpringObjectFactory();        sof.setApplicationContext(appContext);        sof.setAutowireStrategy(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);        map = new HashMap();    } public void testSpringObjectFacotyWithAutowire() { long begin = System.currentTimeMillis(); [...]

遇到了HQL的中文问题:hql的String中包括了中文以后就会出错。经过多次查询,转码(多字节、单字节)还是不能解决问题,说明某些环节压根就对多字节支持不正常。后来经过多次试验,发现是hibernate3的hql语法解释器org.hibernate.hql.ast.ASTQueryTranslatorFactory出的问题,看到有人推荐用org.hibernate.hql.classic.ClassicQueryTranslatorFactory代替。那当然是不可以的,否则相当于退回Hibernate2。解决方法是不要在hql中写中文。而是去使用?占位符和setParameters。比如在Spring HibernateTemplate里面可以:String hql = "select count(*) from Xinfangnews xfnews where xfnews.shifoufabu = 0 and (xfnews.title like ? or xfnews.content like ?)";Object[] parameters = { "%" + keyWord + "%", "%" + keyWord + "%" };getHibernateTemplate().find(hql, parameters);如此可以运行了。不过我走了点弯路:本来写成"like ‘%?%’",然后往里面插keyWord,告诉我找不到?占位符。后来才想到”中的?已经不是占位符了。然后就解决了:所以就是说不能在HQL进行语法解析之前插入中文,而需要在解析之后插入。还要注意,我试验了一下,在Mysql5中已经指定了使用UTF-8语言的时候,不必须在Hibernate连接的地方指明使用jdbc的encoding:如很多人说需要这样配置:<prop key="hibernate.connection.url">jdbc:mysql://10.206.21.171:3306/xinfangweb?useUnicode=true&amp;characterEncoding=GBK&amp;autoReconnect=true</prop>但实际上是用这样的配置:<prop key="hibernate.connection.url">jdbc:mysql://10.206.21.171:3306/xinfangweb</prop>也是可以工作的,当然还是写上比较稳妥。

我们项目升级Weblogic 9.1,所以可以用JDK5的东西了。 先试验一下GenericHibernateDAO,作为一个DAO的基类,实现了一些简单的方法,方便子DAO封装。

使用方法类似:  public class HibernateTownDAO extends GenericHibernateDAO<Town> implements ITownDAO{  {         public HibernateTownDAO() { super(Town.class); } }  }

这个东西基本上是从EclipseWork里面来的……

IGenericDAO大家可以用Eclipse的抽出Interface……

参考这几篇: http://blog.hibernate.org/cgi-bin/blosxom.cgi/Christian%20Bauer/java/…
http://www.hibernate.org/328.htmlhttp://www.matrix.org.cn/thread.shtml?topicId=34892&forumId=26 http://www.javaworld.com.tw/roller/page/ingramchen?entry=2005_10_20_G… 还参考了limo的Blog和limo与徐x赠送的部分代码,thx

代码如下:
package com.goldnet.dao.hibernateDAO;
import org.apache.commons.beanutils.BeanUtils;
import org.hibernate.Criteria;import org.hibernate.Session;
import org.hibernate.criterion.Order;import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.goldnet.dao.IDAO.IGenericDAO;
import java.io.Serializable;
import java.util.Collection;import java.util.Iterator;
/** * @author TIN * @comment  * @param <E> *  * 范型的抽象HibernateDAO,继承于Spring提供的HibernateDaoSupport,该DAO封装了大部分的Domain对象访问方法。 * 使用范型的目的在于可以显示的规定传入/返回的类型。直接的目的在于减少使用DAO时的强行类型转换。 *  * TODO:getTopsByProperty(int, String)方法 * TODO:execute(HibernateCallback [...]

起因是使用Michael Chen的JSValidation,需要手动写onsubmit,结果居然发现webwork 2.2的正式版本里面的form tag里面的onsubmit在使用jsp view的时候没法输出,苦恼于此。暂时通过修改模板修改了一下,但是如此很不爽。所以就想测试一下到底是不是我们项目的问题还是ww 2.2的问题。但一直太忙,今天才抽出功夫测。以下是测试纪录,希望知道缘由的朋友帮我指点一下。
测试使用Webwork发行包中演示的starter项目,其中使用了ftl模板作为表现层,我按它的方式制造了newPerson.jsp。 下面是两个页面的源文件: newPerson.jsp

java代码: 

<%@ page language="java" contentType="text/html; charset=utf-8"%> <%@ taglib uri="webwork" prefix="ww"%> <html> <head>     <title>New Person</title>     <link href="<ww:url value="/webwork/jscalendar/calendar-blue.css" />" rel="stylesheet" type="text/css" media="all"/> </head>
<body> <ww:form action="newPerson" onsubmit="dosomething" validate="false">     <ww:textfield label="Name" name="person.name"/>     <ww:datepicker  name="date" id="ecoInf.turninDate" template="datepicker.ftl" language="en" format="%Y-%m-%d" label="Time"/>     [...]

Hibernate中使用Mysql存储过程 1、我使用了mysql-connector-java-5.0.0-beta-bin.jar(其实用老的mysql-connector-java-3.1.8-bin.jar也可以调用存储过程的)这个最新的mysql驱动。 2、数据库我使用了mysql-5.0.18-win32,安装后建立了一个简单的数据表。 sql如下:

java代码: 

create database testprocedure; use testprocedure; create table testtable (id int(11) AUTO_INCREMENT, content varchar(255), readcount int(11) DEFAULT 0,primary key (id)); desc testtable;(查看是否建立正确)

3、建立一个专用的用户(可选,建立时请使用具有grant权限的用户如root):

java代码: 

grant select,delete,update,create,alter,execute on testtable.* to testprocedure@"localhost" identified by "test";

用户名为testprocedure,密码test。注意权限中的execute,它就是执行call procedure的权限。在你的Hibernate配置中使用该帐户。 4、建立一个存储过程: sql如下:

java代码: 

delimiter // (注意//是新的命令结束符,方便我们建立procedure) create procedure readcountplusone (inputid int) begin update testtable set readcount = readcount + 1 where [...]