- 浏览: 748919 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
lengzl:
请问,那个Node 是哪个包里面的类?
JAVA 二叉树的递归和非递归遍历 -
gongchuangsu:
总结的很好,感谢感谢
JAVA 二叉树的递归和非递归遍历 -
Caelebs:
666666666 居然是10年发的,难怪截屏自动保存的名字是 ...
截图工具 -
jijiqw:
是注解不是注释。。。
Spring @Transactional (一) -
letueo:
[b][b][b][b][b][b][b][b][b][b][ ...
Spring @Transactional (一)
Spring整合Hibernate的价值在于Spring为Hibernate增加了以下内容:
* Session management:Spring为Hibernate的session提供了有效、容易和安全的控制
* Resource management:Spring控制Hibernate的SessionFactories,JDBC datasources及其它相关资源
* Integrated transaction management:完整的事务管理
* Exception wrapping:异常的包装
1. 利用Spring IoC容器创建SessionFactory
可以使用org.springframework.orm.hibernate3.LocalSessionFactoryBean创建SessionFactory实例, 共有以下二种方式:
1) 【最佳方案】直接使用Hibernate配置文件hibernate.cfg.xml
Hibernate配置文件hibernate.cfg.xml如下:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="myeclipse.connection.profile">
com.microsoft.sqlserver.jdbc.SQLServerDriver
</property>
<property name="connection.url">
jdbc:sqlserver://localhost:1433;databaseName=SSH
</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<property name="connection.driver_class">
com.microsoft.sqlserver.jdbc.SQLServerDriver
</property>
<property name="dialect">
org.hibernate.dialect.SQLServerDialect
</property>
<mapping resource="cn/qdqn/ssh/entity/UserInfo.hbm.xml" />
</session-factory>
</hibernate-configuration>
Spring配置文件中SessionFactory初始化配置方法:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml">
</property>
</bean>
2) 在Spring配置文件中整合所有Hibernate配置参数
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"
value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url"
value="jdbc:sqlserver://localhost:1433;databaseName=SSH"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource">
</property>
<property name="mappingResources">
<list>
<value>cn/qdqn/ssh/entity/UserInfo.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</prop>
<prop key="show_sql">true</prop>
</props>
</property>
</bean>
注意:使用MyEclipse集成SSH时,org.apache.commons.dbcp.BasicDataSource所在的包 commons-dbcp-1.2.2.jar不会默认加载,另外还需加载commons-pool-1.4.jar,两者均可在Apache网站 commons项目下找到。否则运行程序会出现以下异常:
java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.getDeclaredConstructor(Unknown Source)
……
2. Hibernate DAO开发
1) 使用Hibernate原生API实现DAO
A. 使用原生API实现DAO
public class UserInfoDAORaw implements IUserInfoDAO {
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public List findAll() {
return this.sessionFactory.getCurrentSession()
.createQuery("from UserInfo").list();
}
部分代码省略……
}
B. 在applicationContext.xml配置原生DAO Bean
<bean id="userInfoDAORaw" class="cn.qdqn.ssh.dao.UserInfoDAORaw">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
C. 运行测试
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAORaw dao=(UserInfoDAORaw)ctx.getBean("userInfoDAORaw");
List<UserInfo> list=dao.findAll();
for(UserInfo info : list){
System.out.println(info.getUserName()+"-"+info.getUserPwd());
}
结论:使用Hibernate原生API实现DAO可以做到Hibernate和Spring完全分离,缺点是无法利用Spring封装Hibernate所提供的额外功能。
2)【最佳方案】使用Spring框架所提供的HibernateDaoSupport类实现DAO
A. 使用MyEclipse反向工程生成Spring 整合Hibernate 的DAO,该DAO继承自Spring的org.springframework.orm.hibernate3.support.HibernateDaoSupport
public class UserInfoDAO extends HibernateDaoSupport {
private static final Log log = LogFactory.getLog(UserInfoDAO.class);
// property constants
public static final String USER_NAME = "userName";
public static final String USER_PWD = "userPwd";
public void save(UserInfo transientInstance) {
log.debug("saving UserInfo instance");
try {
getHibernateTemplate().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}
部分代码省略……
}
B. 在applicationContext.xml配置DAO Bean
<bean id="userInfoDAO" class="cn.qdqn.ssh.dao.UserInfoDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
C. 运行测试
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAORaw dao=(UserInfoDAORaw)ctx.getBean("userInfoDAO");
List<UserInfo> list=dao.findAll();
for(UserInfo info : list){
System.out.println(info.getUserName()+"-"+info.getUserPwd());
}
注意:HibernateDaoSupport通过getHibernateTemplate()方法得到HibernateTemplate实例进行保存、删除等操作,但是HibernateTemplate默认不进行事务处理,而在Hibernate中这些操作必须在事务下执行才能得到正确的结果,因此必须使用Spring声明式事务管理。
3. 使用Spring声明式事务管理
1) 使用Spring 1.x 的事务代理类进行事务管理
A. 在applicationContext.xml中声明事务管理器,注入sessionFactory属性
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
B. 在applicationContext.xml中使用Spring AOP代理方式实现声明式事务
<bean id="userInfoDAOProxy" class=
"org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--必须为true时CGLIB才不用强制编写DAO接口-->
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="userInfoDAO"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
C. 通过代理Bean获取DAO Bean,进行数据库操作
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAO dao=(UserInfoDAO)ctx.getBean("userInfoDAOProxy");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
问题1:运行程序会报以下异常:
java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
at net.sf.cglib.core.ClassEmitter.begin_class(ClassEmitter.java:77)
at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:173)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:117)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104)
at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:69)
…………
解决方法:原因是Spring与Hibernate所使用的asm版本冲突,删除asm.2.2.3.jar即可。
问题2:对每个业务逻辑Bean或DAO Bean都要设置事务代理Bean将是一个非常庞大的工作量!
改进方法: 可以通过定义“基类”来解决重复性编码!如:
<bean id="baseDAOProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="userInfoDAOProxy" parent="baseDAOProxy">
<property name="target">
<ref bean="userInfoDAO"/>
</property>
</bean>
结论:采用Spring 1.x配置事务要额外配置一个代理对象,原来Bean的获取方式也要修改,因此,也是一种“侵入式”的解决方案,虽然没有侵入到Bean程序代码中。
2) 使用Spring 2.x 的aop 和tx 声明式配置进行事务管理
A. 在applicationContext.xml中添加aop和tx名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
…………
</beans>
B. 在applicationContext.xml中声明事务管理器,注入sessionFactory属性
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
C. 通过 <tx:advice>定义事务通知
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="do*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
D. 将事务通知advice和切面pointcut组合起来
<aop:config>
<aop:pointcut id="daoMethods" expression="execution(* cn.qdqn.ssh.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods"/>
</aop:config>
E. 两种应用测试:
a) 对于Java Application,直接获取DAO Bean,进行数据库操作
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAO dao=(UserInfoDAO)ctx.getBean("userInfoDAO");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
问题:运行程序会报以下异常
Exception in thread "main" java.lang.ClassCastException: $Proxy1
at cn.qdqn.ssh.test.AddUserInfo.main(AddUserInfo.java:18)
解决方法:此时唯有JDK 基于接口的代理将起作用,因此每个BO或DAO类必须要有对应的Interface,可以使用MyEclipse的重构功能生成BO或DAO类的接口定义,将获取的BO或DAO Bean放在相应接口对象的引用中即可。代码修改如下:
ApplicationContext ctx=
new ClassPathXmlApplicationContext("applicationContext.xml");
IUserInfoDAO dao=(IUserInfoDAO)ctx.getBean("userInfoDAO");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
b) 对于Web Application,在Struts Action定义BO或DAO,通过Spring在action-servlet.xml中进行注入
public class AddAction extends Action {
private UserInfoDAO userInfoDAO;
public UserInfoDAO getUserInfoDAO() {
return userInfoDAO;
}
public void setUserInfoDAO(UserInfoDAO userInfoDAO) {
this.userInfoDAO = userInfoDAO;
}
…………
}
<bean name="/add" class="cn.qdqn.ssh.struts.action.AddAction">
<property name="userInfoDAO">
<ref bean="userInfoDAO"/>
</property>
</bean>
问题:启动Tomcat会报以下异常
org.springframework.beans.factory.BeanCreationException: Error creating bean with name '/add' defined in ServletContext resource [/WEB-INF/action-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO': no matching editors or conversion strategy found
Caused by:
org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:
PropertyAccessException 1:
org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO': no matching editors or conversion strategy found
…………
解决方法:同Java Application所遇错误相类似,只需将Struts Action定义的等待被注入的BO或DAO替换为其相应的Interface形式即可纠正该错误。如下代码:
public class AddAction extends Action {
private IUserInfoDAO userInfoDAO;
public IUserInfoDAO getUserInfoDAO() {
return userInfoDAO;
}
public void setUserInfoDAO(IUserInfoDAO userInfoDAO) {
this.userInfoDAO = userInfoDAO;
}
…………
}
3) 【最佳方案】使用Spring 2.x 的@Transactional标注进行事务管理
A. 在BO或DAO类中添加事务标注@Transactional
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UserInfoDAO extends HibernateDaoSupport {
private static final Log log = LogFactory.getLog(UserInfoDAO.class);
public static final String USER_NAME = "userName";
public static final String USER_PWD = "userPwd";
public void save(UserInfo transientInstance) {
log.debug("saving UserInfo instance");
try {
getHibernateTemplate().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}
部分代码省略……
}
B. 在applicationContext.xml中添加transactionManager和 <tx:annotation-driven>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
注意:proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。
C. 测试运行,一切正常
ApplicationContext ctx=
new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAO dao=(UserInfoDAO)ctx.getBean("userInfoDAOProxy");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
为了您的安全,请只打开来源可靠的网址
打开网站 取消
来自: http://hi.baidu.com/tlrcn/blog/item/e7af6f0a64ba0338b1351dfc.html
* Session management:Spring为Hibernate的session提供了有效、容易和安全的控制
* Resource management:Spring控制Hibernate的SessionFactories,JDBC datasources及其它相关资源
* Integrated transaction management:完整的事务管理
* Exception wrapping:异常的包装
1. 利用Spring IoC容器创建SessionFactory
可以使用org.springframework.orm.hibernate3.LocalSessionFactoryBean创建SessionFactory实例, 共有以下二种方式:
1) 【最佳方案】直接使用Hibernate配置文件hibernate.cfg.xml
Hibernate配置文件hibernate.cfg.xml如下:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="myeclipse.connection.profile">
com.microsoft.sqlserver.jdbc.SQLServerDriver
</property>
<property name="connection.url">
jdbc:sqlserver://localhost:1433;databaseName=SSH
</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<property name="connection.driver_class">
com.microsoft.sqlserver.jdbc.SQLServerDriver
</property>
<property name="dialect">
org.hibernate.dialect.SQLServerDialect
</property>
<mapping resource="cn/qdqn/ssh/entity/UserInfo.hbm.xml" />
</session-factory>
</hibernate-configuration>
Spring配置文件中SessionFactory初始化配置方法:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation"
value="classpath:hibernate.cfg.xml">
</property>
</bean>
2) 在Spring配置文件中整合所有Hibernate配置参数
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"
value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url"
value="jdbc:sqlserver://localhost:1433;databaseName=SSH"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource">
</property>
<property name="mappingResources">
<list>
<value>cn/qdqn/ssh/entity/UserInfo.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SQLServerDialect
</prop>
<prop key="show_sql">true</prop>
</props>
</property>
</bean>
注意:使用MyEclipse集成SSH时,org.apache.commons.dbcp.BasicDataSource所在的包 commons-dbcp-1.2.2.jar不会默认加载,另外还需加载commons-pool-1.4.jar,两者均可在Apache网站 commons项目下找到。否则运行程序会出现以下异常:
java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.getDeclaredConstructor(Unknown Source)
……
2. Hibernate DAO开发
1) 使用Hibernate原生API实现DAO
A. 使用原生API实现DAO
public class UserInfoDAORaw implements IUserInfoDAO {
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public List findAll() {
return this.sessionFactory.getCurrentSession()
.createQuery("from UserInfo").list();
}
部分代码省略……
}
B. 在applicationContext.xml配置原生DAO Bean
<bean id="userInfoDAORaw" class="cn.qdqn.ssh.dao.UserInfoDAORaw">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
C. 运行测试
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAORaw dao=(UserInfoDAORaw)ctx.getBean("userInfoDAORaw");
List<UserInfo> list=dao.findAll();
for(UserInfo info : list){
System.out.println(info.getUserName()+"-"+info.getUserPwd());
}
结论:使用Hibernate原生API实现DAO可以做到Hibernate和Spring完全分离,缺点是无法利用Spring封装Hibernate所提供的额外功能。
2)【最佳方案】使用Spring框架所提供的HibernateDaoSupport类实现DAO
A. 使用MyEclipse反向工程生成Spring 整合Hibernate 的DAO,该DAO继承自Spring的org.springframework.orm.hibernate3.support.HibernateDaoSupport
public class UserInfoDAO extends HibernateDaoSupport {
private static final Log log = LogFactory.getLog(UserInfoDAO.class);
// property constants
public static final String USER_NAME = "userName";
public static final String USER_PWD = "userPwd";
public void save(UserInfo transientInstance) {
log.debug("saving UserInfo instance");
try {
getHibernateTemplate().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}
部分代码省略……
}
B. 在applicationContext.xml配置DAO Bean
<bean id="userInfoDAO" class="cn.qdqn.ssh.dao.UserInfoDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
C. 运行测试
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAORaw dao=(UserInfoDAORaw)ctx.getBean("userInfoDAO");
List<UserInfo> list=dao.findAll();
for(UserInfo info : list){
System.out.println(info.getUserName()+"-"+info.getUserPwd());
}
注意:HibernateDaoSupport通过getHibernateTemplate()方法得到HibernateTemplate实例进行保存、删除等操作,但是HibernateTemplate默认不进行事务处理,而在Hibernate中这些操作必须在事务下执行才能得到正确的结果,因此必须使用Spring声明式事务管理。
3. 使用Spring声明式事务管理
1) 使用Spring 1.x 的事务代理类进行事务管理
A. 在applicationContext.xml中声明事务管理器,注入sessionFactory属性
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
B. 在applicationContext.xml中使用Spring AOP代理方式实现声明式事务
<bean id="userInfoDAOProxy" class=
"org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--必须为true时CGLIB才不用强制编写DAO接口-->
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="userInfoDAO"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
C. 通过代理Bean获取DAO Bean,进行数据库操作
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAO dao=(UserInfoDAO)ctx.getBean("userInfoDAOProxy");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
问题1:运行程序会报以下异常:
java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
at net.sf.cglib.core.ClassEmitter.begin_class(ClassEmitter.java:77)
at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:173)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:117)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108)
at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:104)
at net.sf.cglib.proxy.Enhancer.<clinit>(Enhancer.java:69)
…………
解决方法:原因是Spring与Hibernate所使用的asm版本冲突,删除asm.2.2.3.jar即可。
问题2:对每个业务逻辑Bean或DAO Bean都要设置事务代理Bean将是一个非常庞大的工作量!
改进方法: 可以通过定义“基类”来解决重复性编码!如:
<bean id="baseDAOProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="userInfoDAOProxy" parent="baseDAOProxy">
<property name="target">
<ref bean="userInfoDAO"/>
</property>
</bean>
结论:采用Spring 1.x配置事务要额外配置一个代理对象,原来Bean的获取方式也要修改,因此,也是一种“侵入式”的解决方案,虽然没有侵入到Bean程序代码中。
2) 使用Spring 2.x 的aop 和tx 声明式配置进行事务管理
A. 在applicationContext.xml中添加aop和tx名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
…………
</beans>
B. 在applicationContext.xml中声明事务管理器,注入sessionFactory属性
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
C. 通过 <tx:advice>定义事务通知
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="do*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
D. 将事务通知advice和切面pointcut组合起来
<aop:config>
<aop:pointcut id="daoMethods" expression="execution(* cn.qdqn.ssh.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods"/>
</aop:config>
E. 两种应用测试:
a) 对于Java Application,直接获取DAO Bean,进行数据库操作
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAO dao=(UserInfoDAO)ctx.getBean("userInfoDAO");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
问题:运行程序会报以下异常
Exception in thread "main" java.lang.ClassCastException: $Proxy1
at cn.qdqn.ssh.test.AddUserInfo.main(AddUserInfo.java:18)
解决方法:此时唯有JDK 基于接口的代理将起作用,因此每个BO或DAO类必须要有对应的Interface,可以使用MyEclipse的重构功能生成BO或DAO类的接口定义,将获取的BO或DAO Bean放在相应接口对象的引用中即可。代码修改如下:
ApplicationContext ctx=
new ClassPathXmlApplicationContext("applicationContext.xml");
IUserInfoDAO dao=(IUserInfoDAO)ctx.getBean("userInfoDAO");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
b) 对于Web Application,在Struts Action定义BO或DAO,通过Spring在action-servlet.xml中进行注入
public class AddAction extends Action {
private UserInfoDAO userInfoDAO;
public UserInfoDAO getUserInfoDAO() {
return userInfoDAO;
}
public void setUserInfoDAO(UserInfoDAO userInfoDAO) {
this.userInfoDAO = userInfoDAO;
}
…………
}
<bean name="/add" class="cn.qdqn.ssh.struts.action.AddAction">
<property name="userInfoDAO">
<ref bean="userInfoDAO"/>
</property>
</bean>
问题:启动Tomcat会报以下异常
org.springframework.beans.factory.BeanCreationException: Error creating bean with name '/add' defined in ServletContext resource [/WEB-INF/action-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO': no matching editors or conversion strategy found
Caused by:
org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessException details (1) are:
PropertyAccessException 1:
org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy1] to required type [cn.qdqn.ssh.dao.UserInfoDAO] for property 'userInfoDAO': no matching editors or conversion strategy found
…………
解决方法:同Java Application所遇错误相类似,只需将Struts Action定义的等待被注入的BO或DAO替换为其相应的Interface形式即可纠正该错误。如下代码:
public class AddAction extends Action {
private IUserInfoDAO userInfoDAO;
public IUserInfoDAO getUserInfoDAO() {
return userInfoDAO;
}
public void setUserInfoDAO(IUserInfoDAO userInfoDAO) {
this.userInfoDAO = userInfoDAO;
}
…………
}
3) 【最佳方案】使用Spring 2.x 的@Transactional标注进行事务管理
A. 在BO或DAO类中添加事务标注@Transactional
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UserInfoDAO extends HibernateDaoSupport {
private static final Log log = LogFactory.getLog(UserInfoDAO.class);
public static final String USER_NAME = "userName";
public static final String USER_PWD = "userPwd";
public void save(UserInfo transientInstance) {
log.debug("saving UserInfo instance");
try {
getHibernateTemplate().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}
部分代码省略……
}
B. 在applicationContext.xml中添加transactionManager和 <tx:annotation-driven>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
注意:proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用。
C. 测试运行,一切正常
ApplicationContext ctx=
new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDAO dao=(UserInfoDAO)ctx.getBean("userInfoDAOProxy");
UserInfo user=new UserInfo();
user.setUserName("比尔盖茨");
user.setUserPwd("windows");
dao.save(user);
为了您的安全,请只打开来源可靠的网址
打开网站 取消
来自: http://hi.baidu.com/tlrcn/blog/item/e7af6f0a64ba0338b1351dfc.html
发表评论
-
Struts2 xwork中ActionContext和ServletActionContext介绍
2011-03-21 11:26 1440ActionContext(Action上下文) ... -
Struts,Hibernate,Spring经典面试题收藏
2010-12-06 08:44 1332Struts,Hibernate,Spring经 ... -
struts1.2中ActionForm的理解
2010-12-03 14:43 1735初学struts的人我认为首 ... -
struts-config.xml 详解
2010-12-03 12:04 966弄清楚struts-config.xml中各项元素的作用,对于 ... -
struts global-exceptions用法
2010-12-03 11:56 1575在用struts框架写web程序时,有可能会遇到很多异常,如u ... -
<servlet-mapping>元素及其子元素
2010-12-03 11:04 1403<servlet-mapping>元素 ... -
servlet mapping 规则
2010-12-03 10:43 1434servlet mapping有三种<url-patte ... -
常用log4j配置
2010-12-03 09:48 926常用log4j配置 常用log4j配置,一般可以采用两种方 ... -
Log4j简介
2010-12-03 09:47 803在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用 ... -
log4j配置祥解
2010-12-03 09:46 994第一步:加入log4j-1.2.8.j ... -
数据库连接池DBCP
2010-12-02 14:54 1060概念:数据库连接池负责分配、管理和释放数据库连接,它允许应用程 ... -
Hibernate持久化对象三种状态的区分,以及save,update,saveOrUpdate,merge,persist等的使用
2010-11-12 20:22 1575Hibernate的对象有3种状态,分别为:瞬时态(Trans ... -
Hibernate持久化对象
2010-11-12 20:20 1225一,持久化对象: 1,置于session管理下的对象叫做持久化 ... -
hibernate核心类简介
2010-11-12 20:16 1165Hibernate Hibernate是一 ... -
J2EE是什么语言
2010-11-11 12:42 5994****** 版权声明 ******** * 在完整保留 ... -
Hibernate最基础的示例
2010-11-04 15:06 1478有关Spring的知识大部分都已经温习完毕,今天开始转向H ... -
struts+spring+hibernate是怎样的架构?
2010-11-01 17:21 1094struts+spring+hibernate是怎 ... -
快速整合struts+spring+hibernate
2010-11-01 17:17 975说明: 使用平台:Eclipse3.2、MyEclipse5 ... -
一些有用的网址
2010-11-01 15:10 1008http://wenku.baidu.com/view/7ab ... -
Spring和Hibernate整合开发
2010-11-01 15:00 1091想的很复杂,用起来就那么回事. 怎么回事呢??? 就是把h ...
相关推荐
标题"spring整合hibernate示例代码"提示我们,我们将讨论如何在实际项目中结合这两个框架。Spring可以帮助管理Hibernate的SessionFactory和Transaction,提供声明式事务管理,以及通过AOP(面向切面编程)实现更灵活...
标题"Spring整合Hibernate.jar"意味着我们将讨论如何将这两个强大的框架集成在一起,以便在Spring管理的环境中使用Hibernate进行数据库操作。这通常涉及到以下步骤和知识点: 1. **引入依赖**:首先,你需要在项目...
本篇文章将详细探讨如何通过Spring整合Hibernate来实现事务处理,重点介绍注解方式和XML配置方式。 首先,我们了解事务处理在数据库操作中的重要性。事务是一组操作,这些操作要么全部成功,要么全部失败,确保数据...
标题中的“spring整合hibernate的jar包”指的是在Java Web开发中,Spring框架与Hibernate持久层框架的集成。这两个框架结合使用可以提供强大的数据访问和业务逻辑处理能力。Spring作为一个全面的轻量级框架,提供了...
本文将深入探讨Spring整合Hibernate的相关知识点,适合初学者入门。 首先,我们需要理解Spring的核心理念。Spring框架提供了一个轻量级的容器,它能够管理应用程序中的对象,包括初始化、配置和依赖注入。AOP则是...
这篇名为"spring整合hibernate实例"的内容,显然是关于如何将这两个框架协同工作,构建一个高效、灵活的Java应用的教程。在整合过程中,我们将探讨以下几个关键知识点: 1. **Spring的ApplicationContext**: 这是...
《Spring整合Hibernate实战指南》 在Java开发领域,Spring框架以其强大的依赖注入、AOP(面向切面编程)以及丰富的模块支持,成为了企业级应用开发的首选。而Hibernate作为持久层框架,以其对象关系映射(ORM)能力...
Spring整合Hibernate是现代Java开发中常见的一种技术组合,利用Spring框架的强大功能来管理和协调Hibernate的持久化操作。Spring为Hibernate提供了全面的集成方案,简化了DAO(Data Access Object)的开发,同时也...
首先,我们需要理解Spring如何与Hibernate和Struts进行整合: 1. **Spring与Hibernate整合**: - Spring通过其`HibernateTemplate`或`HibernateDaoSupport`类简化了对Hibernate的操作,提供了事务管理。你可以定义...
下面,我们将深入探讨Spring整合Hibernate的相关知识点。 1. **依赖注入**:Spring框架的核心特性之一是依赖注入(DI),它允许我们在不进行硬编码的情况下管理对象之间的依赖关系。在整合Hibernate时,Spring可以...
标题"spring整合hibernate与struts2所需jar包"表明我们需要关注的是如何将这三个框架整合在一起,并且提供了所需的一些基础组件。整合SSH可以让开发者利用Spring的管理能力,让Hibernate更易于使用,同时通过Struts2...
《Spring整合Hibernate详解》 在Java企业级应用开发中,Spring和Hibernate是两个非常重要的框架。Spring作为一个全面的轻量级应用框架,提供了强大的依赖注入、AOP(面向切面编程)以及事务管理等功能;而Hibernate...
Spring整合Hibernate配置测试示例
在"spring整合hibernate开发源码"的压缩包中,可能包含了以下内容: 1. **配置文件**:如`applicationContext.xml`,其中配置了Spring和Hibernate的相关bean,如DataSource、SessionFactory、TransactionManager等。...
这里的jar包只是说Spring自带的关于Hibernate的jar包,即这四个jar包: hibernate3.jar, hibernate-annotations.jar, hibernate-entitymanager.jar hibernate-commons-annotations.jar 因为我原来下载了一个,但是...
这个“Spring+hibernate整合源代码”应该包含了实现上述整合步骤的示例代码,可以作为学习和参考的资源。通过学习和实践这些代码,你可以更好地理解和掌握 Spring 和 Hibernate 整合的细节,提升你的 Java Web 开发...
Spring 整合 Hibernate 是一种常见的企业级应用开发模式,它将 Spring 框架的管理优势与 Hibernate 的持久层功能结合起来,提供了更高效、更稳定的应用解决方案。在本学习笔记中,我们将深入探讨如何实现这一整合,...
Spring整合Hibernate基于HibernateTemplate的方式,极大地简化了数据库操作,同时也让事务管理和代码的编写变得更加规范和高效。在实际项目中,可以根据需求进一步配置和优化,比如使用JPA的...
当我们谈到"Spring整合Hibernate例子"时,这意味着我们将探讨如何将这两个强大的框架结合在一起,以实现更高效、更灵活的数据库操作。 Spring框架的核心特性之一是依赖注入(Dependency Injection,DI),这使得...