spring整合hibernate的事务一直错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring整合hibernate的事务一直错误相关的知识,希望对你有一定的参考价值。

spring2.0.hibernate3.0
利用myeclipse自动生成一个SaUser.hbm.xml,SaUser.java,SaUserDAO.java
整合后,不用事务的话,操作数据库正常,如:
public static void main(String[] args)
SaUser user=new SaUser();
user.setUserId("11");
user.setRealName("22");
user.setUserName("33");
user.setPassword("xx");
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
SaUserDAO userdao=(SaUserDAO)context.getBean("SaUserDAO");
userdao.save(user);

之后,根据网上整合事务的方法 ,配置applicationContext.xml如下
<bean id="SaUserDAO" class="wgh.db.SaUserDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

<bean id="myTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="myTransactionManager" />
</property>
<property name="target">
<ref local="SaUserDAO" />
</property>
<property name="transactionAttributes">
<props>
<!-- 这里的方法签名可以精确到方法, 先懒惰一下全配置上 -->
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
之后,把上面的调用方式改为
SaUserDAO userdao=(SaUserDAO)context.getBean("userDAOProxy");
则报错:如下
Exception in thread "main" java.lang.AbstractMethodError: org.springframework.orm.hibernate3.SpringTransactionFactory.beginTransaction(Lorg/hibernate/jdbc/JDBCContext;Lorg/hibernate/transaction/TransactionFactory$Context;)Lorg/hibernate/Transaction;
at org.hibernate.jdbc.JDBCContext.beginTransaction(JDBCContext.java:271)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1079)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:558)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:377)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:263)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
at wgh.db.SaUserDAO$$EnhancerByCGLIB$$4fc8bd33.save(<generated>)
at wgh.action.Test.main(Test.java:18)
LHLBT3GOOD,你好,你的userDaoTarget是哪来的?我上面的该如何改

恩,楼下说的没错,我目前对SPRING的实现机制及原理并不懂,但我现在需要先把功能先实现了,这样理解起来更容易,效率更高,俗话说的好,实践是检验真理的唯一标准。目前找了些资料,并未对单一实现impl(javaben+method)的的讲解,都是bo,boimpl,service即你们常说的什么interface,service,dao,方法应该都是一样的,但我效仿改造都是失败的,没办法才上来问下

说明下,一开始用SaUserDAO userdao=(SaUserDAO)context.getBean("SaUserDAO"); 时,并未用事务,即执行是正常的,后来加了事务配置后,才调用SaUserDAO userdao=(SaUserDAO)context.getBean("userDAOProxy"); 于是,出现如上的错误提示

SaUserDAO userdao=(SaUserDAO)context.getBean("userDAOProxy");
context.getBean("userDAOProxy"); 是说从spring环境context中拿出id=userDAOProxy对象.再把这个对象强制转换成SaUserDAO.
你改成
SaUserDAO userdao=(SaUserDAO)context.getBean("SaUserDAO");
你把userDAOProxy对象强转成SaUserDAO,这样行不?
关键是要明白spring做了什么
你的配置文件sessionFactory有没有进行配置
SPRING就是一个IOC容器,简单来讲我们平常一般是NEW一个对象.
有了SPRING后,将对象配置在SPRING后,我们就可以从SPRING的容器里面拿出那些对象了直接用.也就是所谓的注入.
比如说:你在A类中,要调用B类的方法时,通常是new一个B的实例.
用SPRING的话,只用在A中加一个属性 B b;然后在配置文件中将A的属性b进行配置就可以了.
<bean id="b" class="B">
<bean id="a" class="wgh.db.A">
<property name="b">
<ref bean="b" />这里的b就是上面的id=b的那个值
</property>
</bean>
关于SPRING的代理
AOP代理
Spring缺省使用J2SE 动态代理(dynamic proxies)来作为AOP的代理。 这样任何接口(或者接口集)都可以被代理。
Spring也可以使用CGLIB代理. 对于需要代理类而不是代理接口的时候CGLIB代理是很有必要的。如果一个业务对象并没有实现一个接口,默认就会使用CGLIB。
简单来讲,你的类没有实现接口就得强制使用CGLIB来代理.类实现了接口默认采用JDK的动态代理机制实现AOP.

强制使用CGLIB生成代理.
1在spring配置文件中加入
<aop:aspectj-autoproxy proxy-target-class="true"/>
2 加入CGLIB库
spring/lib/cglib/*.jar

spring对事务的管理也就是AOP了
推荐你一个不错的视频
http://www.verycd.com/topics/93279/

我复制一个我学习时用到的配置文件
Spring与hibernate的集成
要控制事务,就得要拿到hibernate的session. hibernate的session获得方式:sessionfactory.sessionfactory的创建configuration,configuration的获得就由配置文件了.Spring整合Hibernate主要是对hibernate的Session进行管理,包含Session的创建、提交、关闭的整个生命周期。此处的session可以看作是一个connection.
声明式事务的配置
1配置sessionfactory
2配置事务管理器
3配置事务的传播特性
4配置哪些哪些方法使用事务

<!--配置sessionfactory -->
配置sessionFactory,让spring来创建Session。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name=" configLocation ">
<value>classpath:hibernate.cfg.xml</value>hibernate的配置文件
</property>
</bean>
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"//只适合xml方式
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean//兼容注解

<!-- 配置事务管理器 -->
把sessionFactory拿过来放到事务管理器里. 创建了一个id为transactionManager的事务管理器,它匹配一个session工厂,<ref bean="sessionFactory"/>这个sessionFactory是指session工厂的ID。
<bean
id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="beanFactory" ref=” sessionFactory”/>
</bean>

<!-- 配置事务的传播特性 -->
这里创建了一个advice(通知),对事务管理器进行事务设置,这里意思是指,对于以save、del、update开头的方法应用事务。
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置哪些哪些方法使用事务 -->
配置的作用是把我们上面创建的advice应用到具体的类中。以下代码的意思指,给包com.spring下的所有类的所有方法应用allManagerMethod()方法.
<aop:config>
<aop:pointcut id="allManagerMethod" expression="execution(* com.spring.*.*(..))"/>com.spring包下所有的类所有的方法
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod"/>advisor可以理解为一个aspect,一个aspect一般有pointcut,advice.
</aop:config>

你学习这个最好弄懂SPRING的原理
IOC,AOP这些概念原理什么的
参考技术A <bean id="userDao"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置事务管理器 -->
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="userDaoTarget" />
<property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
<!-- 配置事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

正确的配置方式!

特别要注意的是property的name属性是不能改的!
参考技术B 按lz你的配置
SaUserDAO userdao=(SaUserDAO)context.getBean("SaUserDAO")
这句注入的是SaUserDAO而不是代理对象userDAOProxy

以上是关于spring整合hibernate的事务一直错误的主要内容,如果未能解决你的问题,请参考以下文章

spring与hibernate整合事务管理的理解

hibernate4整合spring3事务问题

Spring整合hibernate4:事务管理

Spring与Hibernate整合,实现Hibernate事务管理

hibernate与spring整合

spring hibernate 事务整合 使用测试类 事务不自动提交的问题!!!