3

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

根上下文.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 函数,这是可行的,但我不明白为什么。

4

2 回答 2

3

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

1) 您的服务 bean 在一个单独的 ApplicationContext 中,它没有启用注释驱动的事务。

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

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

于 2012-05-30T03:45:05.523 回答
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
于 2013-01-12T15:07:51.023 回答