将Service类标记为Transactional时,DAO中没有找到“当前线程的会话”错误

时间:2012-05-29 22:41:29

标签: spring hibernate transactions annotations

使用Hibernate 4和Spring 3.1。刚开始运行它,所以这可能是我缺乏理解。我在Service类中有一个方法,它调用DAO类中的方法以使用Hibernate检索一些数据。我使用@Transactional注释Service方法,但在DAO方法中调用getCurrentSession时出错。如果我使用@Transactional注释DAO方法,则成功检索数据。我不明白为什么 - 我会想到Service方法上的@Transactional注释会创建一个Hibernate会话,将它绑定到线程,并且当调用getCurrentSession时,会话将在DAO类中返回。任何人都可以解释为什么会这样,或者我做错了什么,谢谢?

根的context.xml:                   

<tx:annotation-driven transaction-manager="transactionManager"/>

服务类:

public class BlahServiceImpl implements BlahService {

    @Transactional  
    public Blah GetMostRecentBlah() {
        BlahDAO blahDAO = DAOFactory.GetBlahDAO();
        return blahDAO.GetMostRecentBlah();
    }
}

DAO课程:

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}

public Blah GetMostRecentBlah() {
    return (Blah)sessionFactory.getCurrentSession().createQuery("from Blah where blahID = (select max(blahID) from Blah)").uniqueResult();
}

错误:

org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1039)
com.blah.blah.DAO.BlahDAOImpl.GetMostRecentBlah(BlahDAOImpl.java:18)

就像我说的,如果我使用@Transactioanl(以及Service方法)注释DAO函数,这可行,但我不明白为什么。

2 个答案:

答案 0 :(得分:3)

两个可能的原因表明了自己。

1)您的服务bean位于单独的ApplicationContext中,该ApplicationContext没有启用注释驱动的事务。

2)您正在获取对您的服务实例的引用,该实例是原始实例,而不是代理的,因此是事务性实例。

要确定哪个是您的问题,或确定是否存在其他问题,请显示导致您的服务bean创建的上下文文件,并显示您获取服务实例的代码。

答案 1 :(得分:1)

解决方案可能是:

<tx:annotation-driven proxy-target-class="true"  transaction-manager="transactionManager" />

因为没有代理类。

否则,如果你必须将私有方法代理为事务性(就像我所面对的那样),你最终可能会添加aspectj而不是cglib,然后配置可能有帮助

 <!-- switches on the load-time weaving -->
    <context:load-time-weaver />

    <!--  proxies classes with aspectj and you may have @Transaction annotations for managing transactions-->    
    <tx:annotation-driven proxy-target-class="true"   mode="aspectj" transaction-manager="transactionManager" />

之后用jvm参数启动服务器

-javaagent:/path-to/spring-instrument-{spring-version}.jar