全面整合spring管理struts,spring管理hibernate

黄金组合之全面整合,让spring管理struts,spring管理hibernate

一、新建web工程,ssh

1.导入struts,选择struts1.2的jar包

建立包:org.accp.struts

copy到当前目录下

2.导入spring

选择jar包,注意不要导入hibernate2的包,其它全要。

然后是applicationContext.xml放在src下,方便后期测试

后期可以放到webRoot/web-inf下

有重复的,选择覆盖

copy到当前目录下

3.导入hibernate,

要选3.0,spring不支持3.1

选中copy...,再next

选中生成在spring配置文件

再next,选中已经存在的配置文件

再写sessionFactoryID=sessionFactory,next

填写数据源,beanid=ds,再next

去掉createsessionFactoryclass代表全部由spring托管

覆盖

4.建立包:

org.accp.hibernate

org.accp.hibernate.po

org.accp.hibernate.dao

org.accp.well.delegate

5.导入日志配置文件src/log4j.properties

6.导入mysql.jar,不能拷贝到lib下,也找不到,这时要在buildPath中导入外部jar

7.如果报错:<url>这里不能有空格或回车符</url>

二、spring整合hibernate

1.查看applicationContext.xml有了变化,多了hibernate的配置

2.建立表的映射

选择数据库视图,accp数据库

生成users.hbm.xml与Users.java

去掉catagory属性,否则会报错

也在applicationContext.xml中增加了映射

3.整合hibernate有两种方式

4.第一种方式,继承

org.springframework.orm.hibernate3.HibernateTemplate,该类是spring封装了操作Hibernate的实现细节的类,用于代替Session的相关操作。主要方法:

Serializablesave(Object?entity):保存记录

voidupdate(Object?entity):修改记录

voiddelete(Object?entity):删除记录

Objectget(Class?entityClass,Serializable?id)

Objectload(Class?entityClass,Serializable?id)

ListexecuteFind(HibernateCallback?action):查询,返回集合

Objectexecute(HibernateCallback?action):查询,返回对象

总的说来,该类的方法和Session接口中定义的方法是一致的.

1)在dao包中写接口IDao,

publicinterfaceIDao{

publicvoidsave(Usersu);

publicListgetAll();

publicbooleanvalidate(Usersu);

}

UserDaoextendsHibernateDaoSupportimplementsIDao

publicclassUserDaoextendsHibernateDaoSupportimplementsIDao{

publicvoidsave(Usersu){

this.getHibernateTemplate().save(u);

}

}

2)在spring中配置UserDao,从哪取连接,property二择其一

给继承了HibernateDaoSupport的对象我们注入一个sessionFactory对象也可以,他会自动生成一个hibernateTemplate对象

<beanid="userdao"class="org.accp.hibernate.dao.UserDao">

<propertyname="sessionFactory"ref="sessionFactory"/>

<!--<propertyname="hibernateTemplate"ref="hibernateTemplate"/>-->

</bean>

3)测试

导入mysql.jar,不能拷贝到lib下,也找不到,这时要在buildPath中导入外部jar

去掉users.hbm.xml中的catagory属性,否则会报错

////////////////////////////////////ApplicationContextac=newClassPathXmlApplicationContext("applicationContext.xml");

IDaodele=(IDao)ac.getBean("userdao");

Usersu=newUsers();

u.setUid("userdao");

u.setPwd("123");

u.setVersion(2);

dele.save(u);

5.第二种方式

1)新建一个类UserDao2,加一成员变量HibernateTemplate

加一构造函数,注入sessionFactory

加一setter方法,注入sessionFactory

publicclassUserDao2implementsIDao{

privateHibernateTemplatehibernateTemplate;

publicUserDao2(HibernateTemplatehibernateTemplate){

this.hibernateTemplate=hibernateTemplate;

}

publicvoidsave(Usersu){

hibernateTemplate.save(u);

}

}

2)改配置文件applicationContext.xml

<beanid="userdao2"class="org.accp.hibernate.dao.UserDao2">

<constructor-arg>

<refbean="hibernateTemplate"/>

</constructor-arg>

</bean>

<beanid="hibernateTemplate"class="org.springframework.orm.hibernate3.HibernateTemplate">

<propertyname="sessionFactory">

<refbean="sessionFactory"/>

</property>

</bean>

6.HibernateDaoSupport与连接的管理

而调用getHibernateTemplate()就会自动关闭连接。

这是日志

[main]DEBUGorg.springframework.orm.hibernate3.SessionFactoryUtils-ClosingHibernateSession

自动关闭连接会造成延迟加载初始化异常,此时可用OpenSessionInView模式解决。Spring提供OpenSessionInView来解决这个问题,有两种方式。

1)Interceptor,在applicationContext.xml配置

<beanid="openSessionInViewInterceptor"class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">

<propertyname="sessionFactory"ref="sessionFactory"/>

</bean>

<beanid="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<propertyname="interceptors"ref="openSessionInViewInterceptor"/>

<propertyname="mappings">

<props>

......

</props>

</property>

</bean>

2)Filter,在web.xml中配置

<filter>

<filter-name>hibernateFilter</filter-name>

<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>

<!--默认情况下,这个Filter会在Spring的bean池中找一个叫做sessionFactory的bean。如果使用了其他名字的SessionFactory,则应该在这里-->

<init-param>

<param-name>sessionFactoryBeanName</param-name>

<param-value>sessionFactory</param-value>

</init-param>

<!--singleSession默认为true,若设为false则等于没用OpenSessionInView-->

<init-param>

<param-name>singleSession</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>hibernateFilter</filter-name>

<url-pattern>*.do</url-pattern>

</filter-mapping>

加了这个配置,就要加监听器和初始文件的参数,否则报错

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/applicationContext.xml</param-value>

</context-param>

<listener>

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

</listener>

7.HibernateDaoSupport与自动提交

每执行一个sql,默认都是由spring自动提交事务。可以在数据源中插入进去

<propertyname="defaultAutoCommit">

<value>false</value>

</property>

8.spring整合hibernate事务

Don'tcallme,Iwillcallyou

更少代码,更少BUG

Spring提供的事务管理可以分为两类:编程式的和声明式的。

1)编程式的

比较灵活,但是代码量大,存在重复的代码比较多,当你只有很少的事务操作时,编程式事务管理通常比较合适。

代码

publicclassUserDao3extendsHibernateDaoSupportimplementsIDao{

privateHibernateTransactionManagertransactionManager;

publicvoidsetTransactionManager(HibernateTransactionManagertransactionManager){

this.transactionManager=transactionManager;

}

publicvoidsave(Usersu){

DefaultTransactionDefinitiondef=newDefaultTransactionDefinition();

TransactionStatusstatus=transactionManager.getTransaction(def);

try{

this.getHibernateTemplate().save(u);

//不提交插入不了

transactionManager.commit(status);

}catch(Exceptione){

transactionManager.rollback(status);

}

}

}

配置

<beanid="userdao3"class="org.accp.hibernate.dao.UserDao3">

<propertyname="sessionFactory"ref="sessionFactory"/>

<propertyname="transactionManager"ref="transactionManager"/>

</bean>

<beanid="transactionManager"

class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<propertyname="sessionFactory">

<refbean="sessionFactory"/>

</property>

</bean>

2)声明式的

其DAO必须要有接口,否则声明式事务就会报错。

a)事务属性

<propkey="save*">PROPAGATION_REQUIRED,readOnly</prop>

key属性确定代理应该给哪个方法增加事务行为。PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务,避免dirtychecking。

b)事务策略

为了实际执行事务,Spring所有的事务划分功能都通过传递适当的TransactionDefinition实例,委托给PlatformTransactionManager。

Spring具有多种PlatformTransactionManager实现,它们分为两类:

局部事务策略--针对单个资源执行事务(在多数情况下是针对单个的数据库)。

全局事务管理--执行有可能跨越多个资源的全局事务。

c)事务代理

TransactionProxyFactoryBean是Spring2.0之前的旧版本风格的配置

TransactionInterceptor,它使用一个PlatformTransactionManager实现配合,在方法调用前后实施事务。

d)例子

配置文件

<beanid="userdao4"class="org.accp.hibernate.dao.UserDao4">

<propertyname="sessionFactory"ref="sessionFactory"></property>

</bean>

<beanid="proxyTemplate"class="org.springframework.transaction.interceptor.TransactionInterceptor">

<propertyname="transactionManager">

<refbean="transactionManager"/>

</property>

<propertyname="transactionAttributes">

<props>

<propkey="save*">PROPAGATION_REQUIRED</prop>

<propkey="query*">PROPAGATION_REQUIRED,readOnly</prop>

</props>

</property>

</bean>

<beanid="nameproxy"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

<propertyname="beanNames">

<list><value>userdao4</value></list>

</property>

<propertyname="interceptorNames">

<list>

<value>proxyTemplate</value>

</list>

</property>

</bean>

不用事务,即使报错也始终能插入进去一条。用了事务,一报错则一条都不进去。

配置完成前,将defaultAutoCommit设成false后,始终插入不进去。

配置完成后,将使用声明式事务能插入进去了。

9.sql提高,修改UserDao

//executeFind返回集合

publicListquery(){

returnthis.getHibernateTemplate().executeFind(newHibernateCallback(){

publicObjectdoInHibernate(Sessionsession)throwsHibernateException,

SQLException{

returnsession.createQuery(

"from"+cls.getName()+"asaorderbya.uiddesc").list();

}

});

}

//execute返回对象

publicbooleanvalidate(finalUsersu){

Listls=(List)this.getHibernateTemplate().execute(

newHibernateCallback(){

publicObjectdoInHibernate(Sessionsession)

throwsHibernateException,SQLException{

Queryqy=session

.createQuery("fromUsersuwhereu.uid=:uidandu.pwd=:pwd");

qy.setString("uid",u.getUid());

qy.setString("pwd",u.getPwd());

Listli=qy.list();

returnli;

}

});

return(ls.size()>0);

}

三、spring整合struts

1.在struts-config.xml中新建login用例

form/action/jsp,usecase=login

2.写代理UserDelegate,有保存、验证、查询所有的记录三个方法

源代码

publicclassUserDelegate{

//一定要是IDao而不是UserDao,因为有了事务,自动代理将截获后返回的是IDao

privateIDaodao;

publicvoidsetDao(IDaodao){

this.dao=dao;

}

publicbooleanvalidate(Stringuid,Stringpwd){

returndao.validate(uid,pwd);

}

publicListgetAll(){

returndao.getAll();

}

publicvoidsave(Usersu){

dao.save(u);

}

}

配置文件

<beanid="ud"class="org.accp.well.delegate.UserDelegate">

<propertyname="dao"ref="userdao"></property>

</bean>

3.加上跳转页面

新增succ.jsp

succ对应succ.jsp,fail对应login.jsp

4.引入IOC,在action中引入代理

修改LoginAction

privateUserDelegateud;

publicvoidsetUd(UserDelegateud){

this.ud=ud;

}

5.在action中写上登陆验证代码

Stringuid=loginForm.getUid();

Stringpwd=loginForm.getPwd();

if(ld.validate(uid,pwd))

returnmapping.findForward("succ");

returnmapping.findForward("fail");

6.在struts中引入spring

在struts-config.xml中注册,引入spring的插件,在message-resources标签后:

<plug-inclassname="org.springframework.web.struts.ContextLoaderPlugIn">

<set-propertyproperty="contextConfigLocation"value="/WEB-INF/classes/applicationContext.xml"/>

</plug-in>

7.让spring管理struts的action,有三种方式

1)最简单的一种,改变其请求处理器:

<controllerprocessorclass="org.springframework.web.struts.DelegatingRequestProcessor"/>

2)在struts的action中直接继承spring的一个ActionSupport

3)改action的配置中的type,换成spring的一个代理,这个每个action都要改,比较麻烦

<type="org.springframework.web.struts.DelegatingActionProxy">

8.采用第一种方式

在spring的applicationContext.xml中注册struts的action

其name(不能是id)对应于struts-config.xml中的path

<beanname="/login"class="org.accp.struts.action.LoginAction">

<propertyname="ud"ref="ud"></property>

</bean>

四、部署运行

1.发布

2.如果导入spring时,没有选中web的jar包,则集成到struts会出错

3.测试一切正常

4.将applicationContext.xml放到与web.xml平级目录

修改struts-config.xml的配置,改<plug-in>路径

再测试一切正常

5.将与struts的集成改成第一种方式

改<action>标签的type

<controllerprocessorclass="org.springframework.web.struts.DelegatingRequestProcessor"/>

再测试一切正常

6.看日志,session的开闭

[http-8080-Processor25]DEBUGorg.springframework.orm.hibernate3.SessionFactoryUtils-OpeningHibernateSession

...

[http-8080-Processor25]DEBUGorg.hibernate.impl.SessionImpl-closingsession

相关推荐