首先说点题外话,框架整和时一定要考虑框架的兼容。之前我用的是hibernate 5出现许多莫名的错误,换成低版本后错误就解决了。
下面进入正题。问题:之前我在applicationContext.xml里只配置了dataSource与sessionFactory,没有配置事物管理,当我在代码中用se.getCurrentSession()时报错:org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
我上网查询了一通说是要配置事物管理,配置事物管理有多种方法 ,大家可以看看这个博客介绍了五种配置事物管理的方法http://blog.csdn.net/it_man/article/details/5074371
我采用的是注解方式,代码如下:
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
然后在方法前加上注解@Transacational,满以为这样就大功告成,测试时又出现错误:
java.lang.NoSuchMethodException: $Proxy12.login()
什么?没有这个方法?怎么可能?再看看Proxy12.login(),怎么有代理。什么鬼。
原来:
Spring的事务管理机制实现的原理,就是通过一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的 方法名进行判定,并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。
spring中代理对象的生成方式有2种,
1:利用jdk中的proxy实现,要求我们的被代理对象必须要去实现一个代理接口,代理对象和被代理对象本质是是实现了统一接口的两个对象
2:利用cglib来实现.被代理对象不需要去实现一个代理接口,被代理类和代理类之间本质是父子类的关系
proxy-target-class="true" 指定由cglib来实现实现代理.
看到这我就明白了,我的userAction是继承supportAction,spring是默认jdk的proxy生成代理对象,只能代理接口方法,userAction没有实现接口所以报错。修改代码如下
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
大功告成。