添加@Transactional时无法初始化dao bean

时间:2016-02-21 10:15:41

标签: spring transactional cglib

在遗留项目的dao中我添加了一个新方法,然后我编写了一个单元测试来测试新方法

FooDAO dao = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}).getBean("FooDAO");  
@Test
public void test_getUnenabledArtisanIdsByReverseTime(){
    String reverseTimeStr = "2016-02-18 19:00";
    List<String> artisanIds = new ArrayList<>();
    artisanIds.add("1");
    artisanIds.add("2");
    dao.getUnenabledArtisanIdsByReverseTime(artisanIds, reverseTimeStr);
}

失败,抛出异常

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

然后我在applicationContext.xml

中添加以下配置
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

并在新方法

上方添加@Transactional
@Transactional
public List<String> getUnenabledArtisanIdsByReverseTime(List<String> artisanIds, String reverseTimeStr) 

然后再次执行单元测试,也失败,但这是另一个例外

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'FooDAO' defined in file [/home/zhuguowei/workspace/myapp/WebContent/WEB-INF/classes/com/foo/artisan/repository/FooDAO.class]: 
Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: 
Could not generate CGLIB subclass of class [class com.foo.artisan.repository.FooDAO]: 
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:527)
很奇怪,dao是公开的而不是最终的类

@Component
public class FooDAO extends BaseDaoHiber4Impl<Foo>

public BaseDaoHiber4Impl() {
    this.entryClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

那么这个问题的原因是什么,以及如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

cglib代理通过创建新类,扩展目标类和覆盖每个方法来工作。

创建代理时,构造函数失败:

(ParameterizedType) getClass().getGenericSuperclass()

getClass()现在是代理,getGenericSuperclass()是当前类(FooDAO),它不是ParameterizedType

可能的解决方法:

  1. 看起来你正试图重新实现spring-data:试一试: - )
  2. 不要使用cglib代理:为你的DAO定义一个接口,让FooDAO实现它,并注入这个接口而不是你的类。
  3. 处理FooDAO扩展的情况:遍历所有getGenericSuperclass()以查找第一个ParameterizedType实例