各位好,小弟初学Spring想通过AOP配置将Hibernate数据库事务扩展到DAO层,防止出现懒加载异常。可是通过配置发现在进行单元测试时系统一直报错,所以特来请教请各位帮忙看看是什么问题,谢谢了!以下为Spring 事务配置文件:<bean id="sessionFactory"  
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
     <property name="configLocation"  
         value="file:src/hibernate.cfg.xml">  
     </property>  
 </bean>  
   
 <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
     <property name="sessionFactory" ref="sessionFactory" />  
 </bean>  
   
 <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">  
     <property name="sessionFactory">  
         <ref bean="sessionFactory" />  
     </property>  
 </bean>  
   
   
  <aop:config proxy-target-class="true">  
        <aop:advisor pointcut="execution(* mycompy.servicesystem.dao..*.*(..))"  
            advice-ref="txAdvice"/>  
     </aop:config>  
     <tx:advice id="txAdvice" transaction-manager="transactionManager">  
        <tx:attributes>  
            <tx:method name="add*" rollback-for="java.lang.Throwable"/>            
            <tx:method name="modify*" rollback-for="java.lang.Throwable"/>  
            <tx:method name="find*,get*,is*,has*" read-only="true"/>  
            <tx:method name="*" rollback-for="java.lang.Throwable"/>  
       </tx:attributes>  
     </tx:advice>  
   
 <bean id="areaDao" class="mycompy.servicesystem.dao.impl.AreaDaoImpl">  
     <property name="hibernateTemplate" ref="hibernateTemplate" />  
 </bean>  
 其中的DAO层我有使用了泛型结构大致如下:
AreaDaoImpl.java  public class AreaDaoImpl extends HibernateDaoImpl<Area, String> implements  
         IAreaDao {  
 ............  
 } 
 HibernateDaoImpl.java public class HibernateDaoImpl<T extends Identifiable, PK extends Serializable> extends  
        HibernateDaoSupport {  
  public Class<T> queryClass; @SuppressWarnings("unchecked")
public HibernateDaoImpl() {
Type genType = getClass().getGenericSuperclass();
Type[] parames = ((ParameterizedType) genType).getActualTypeArguments();//这一行有错
queryClass = (Class) parames[0];
}
......}  
系统报的错误是:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'areaDao' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class mycompany.servicesystem.dao.impl.AreaDaoImpl]: Common causes of this problem include using a final class or a non-visible class; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
at mycompany.servicesystem.common.ContextUtil.getApplicationContext(ContextUtil.java:11)
at mycompany.servicesystem.dao.TestDepartmentDao.setUp(TestDepartmentDao.java:39)
BeforeAndAfterRunner.java:74)
at org.junit.internal.runners.BeforeAndAfterRunner.runBefores(BeforeAndAfterRunner.java:50)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:33)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
... 35 more
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:235)
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:220)
... 41 more
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at mycompany.servicesystem.dao.base.impl.HibernateDaoImpl.<init>(HibernateDaoImpl.java:50)
at mycompany.servicesystem.dao.impl.AreaDaoImpl.<init>(AreaDaoImpl.java:26)
at mycompany.servicesystem.dao.impl.AreaDaoImpl$$EnhancerByCGLIB$$f9ab0600.<init>(<generated>)
... 49 more 网上我也查了一下资料,把下文中的proxy-target-class="true"去掉。 <aop:config proxy-target-class="true">  
  <aop:advisor pointcut="execution(* mycompy.servicesystem.dao..*.*(..))"  advice-ref="txAdvice"/>  
</aop:config>  程序虽然不在启动时抛异常,而在进行查询时抛的异常,这个异常我看了一下是与懒加载有关的,我查了一下我的代码,我的确进行了延迟加载。但我又有一个疑问,我不是给所有的DAO加了事务处理了吗,那也就意味着在事务中会打开Session应该不存在懒加载的问题。但这里却有这个问题请大家帮帮我!!!!下文是去除proxy-target-class="true"后系统给的异常信息 
(hibernate.LazyInitializationException 19  ) failed to lazily initialize a collection of role: mycompany.servicesystem.entities.Area.Departments, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mycompany.servicesystem.entities.Area.Departments, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.toArray(PersistentSet.java:146)
at java.util.ArrayList.<init>(ArrayList.java:131)
at mycompany.servicesystem.dao.impl.AreaDaoImpl.getDepartmentById(AreaDaoImpl.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy7.getDepartmentById(Unknown Source)
at mycompany.servicesystem.dao.TestAreaDao.testGetDepartmentById(TestAreaDao.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)附:有的大虾可能会说我为什么把事务放在DAO层,那是因为我现在正进行DAO层代码编写后继我会放在Service层去的,所以请大虾回答问题时不要指出这点问题! 

解决方案 »

  1.   

    spring配置事务这一块,我也要好好研究一下,以前没有注意这一块
      

  2.   

    大体我也遇到过,问了别人,把我的理解和你说下。。希望对你有用。不对的高手指正。
    第一个:为什么会代理对象错误。Spring的AOP编程采用的是动态代理机制,分两种方法:JDK代理和CGLIB代理。前者要求被代理类实现一个接口。就是你添加事务的DAO要实现一个接口。CGLIB代理则不需要被代理类(你的DAO类)实现接口。Spring会自动根据你的被代理类(添加事物控制的地方)是否实现接口来选择采用哪种代理。proxy-target-class="true" 你写了这句。他的意思是:不要给我自动检查,我就用CGLB代理。因为你的被代理类实现了接口,当然报错。去掉了,自动检查——实现接口——Spring采用了JDK代理处理事务。第二个没遇到过,但是Hibernate对事务的控制,本身就是在DAO层的啊。。你用了Spring+Hibernate的框架,应该是Spring会自动帮你在DAO层关掉session(hibernate的DAO代码中是没有关session的代码的)。那你又在DAO层加了事务控制,感觉还是一样的,本身就在那里关,你也在那里关。当然会报LIZ异常啊。高手指正
      

  3.   

    To:#2楼的兄弟   呵呵,首先申明一下我也是一个菜鸟,所以我说的也不一定对,只是基于自己的想法想和大家交流一下。   你说的Spring的AOP编程的确就像你说的那两种方法的确是这样子的,但是我看了网上有很多例子,他们在有采用接口的形势下也有采用CGLB代理。只是有的人反应这种AOP方式对集成泛型有点问题。至于原因由于比较抽象我一时也理解不了。   不过还是很感谢你,你的想法也是不错的。   还有就是你说的Hibernate事务控制本身就在DAO层的观点,我觉的有点问题因为我在代码是使用的是HibernateDaoSupport,这个是由Spring提供的Hibernate模板。基中的事务与Session控制应该都封装在内。对于我们自己写的DAO层代码,我觉的还是需要加上事务控制的。   不过一般大家的事务控制都是加在Service层,所以这时在DAO层的话你会感觉到Hibernate在进行事务管理。   呵呵,这次比较特殊,我在写DAO层单元测试时由于Lazy异常比较反感,所以想把事务处理加在这层上面等这层的代码基本稳定后再把事务放在Service层。所以我才遇到这个问题。。
       
      

  4.   

    你可以买本陈雄华的spring看一下,那上面对aop讲的特别的细,并且那本书有这么教你写通用的dao层。
      

  5.   

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'areaDao' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class mycompany.servicesystem.dao.impl.AreaDaoImpl]: Common causes of this problem include using a final class or a non-visible class; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType