简体   繁体   English

使用Hibernate 4中的事务功能是否需要JTA管理器

[英]Is JTA manager necessary to use transaction features in hibernate 4

I'm following the tutorial here: http://www.javacodegeeks.com/2013/05/hibernate-4-with-spring.html to enable the "@Transactional annotation" in my Java web application but failed to make it run properly. 我在这里关注该教程: http : //www.javacodegeeks.com/2013/05/hibernate-4-with-spring.html在我的Java Web应用程序中启用“ @Transactional批注”,但未能使其运行正确地。 Please advise if the JTA manager is really required, and why? 请告知是否真的需要JTA经理,为什么?

Please note that my webapp is based on Spring 3 + Hibernate 4 + Tomcat 7. 请注意,我的Web应用程序基于Spring 3 + Hibernate 4 + Tomcat 7。

Background and my doubts: 背景和我的疑问:

My current web application uses my own custom class (implements HandlerInterceptor) to enable one-hibernatesession-per-request basis. 我当前的Web应用程序使用我自己的自定义类(实现HandlerInterceptor)来启用每个请求一个休眠会话的基础。 Now I want to improve my application's maintainability by using the "@Transactional annotation" instead since that could save many lines of code. 现在,我想使用“ @Transactional注解”来提高应用程序的可维护性,因为那样可以节省很多行代码。

According to my understanding, the @Transactional basically relies on the AOP concept to ensure the session (Hibernate session) is ready for use in the annotated method. 根据我的理解,@ Transactional基本上依靠AOP概念来确保会话(Hibernate会话)可以在带注释的方法中使用。 This seems nothing to do with the JTA. 这似乎与JTA无关。 But I wonder why can't I make it work on my webapp in Tomcat 7 (without JTA-provider). 但是我不知道为什么不能使其在Tomcat 7中的Web应用程序上运行(没有JTA提供程序)。

After few searches on google, it looks like the JTA is required. 在Google上进行几次搜索后,看来JTA是必需的。 This confuses me since this seems to be a very basic functionality that shouldn't have the complicated JTA-provider as a requirement. 这使我感到困惑,因为这似乎是一个非常基本的功能,不应该要求复杂的JTA提供程序。

Here is the error I got: 这是我得到的错误:

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:988)
    ...

This is the code I use for testing: 这是我用于测试的代码:

....

@Autowired
org.hibernate.SessionFactory sessionFactory;

@Transactional
@RequestMapping(method = RequestMethod.GET)
protected String home() {
    Session session = sessionFactory.getCurrentSession(); // I expected the session is good to use now
    Province p = (Province) session.get(Province.class, 1L); // This causes no session found error :(


    return "home";
}

The spring XML: 春季XML:

....
<tx:annotation-driven/>
<context:component-scan base-package="..."/>

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/..."/>
    <property name="lookupOnStartup" value="true"/>
    <property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>

            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
....

Thank you ! 谢谢 !

Just a speculation: 只是一个推测:

Your controller is defined in some kind of dispatcher-servlet.xml therefore seperates from the applicationContext in which < tx:annotation-driven/> is defined. 您的控制器是在某种类型的dispatcher-servlet.xml中定义的,因此与定义<tx:annotation-driven />的applicationContext分开。 The compoment you want to enhance with @Transactional need to be within the same context with < tx:annotation-driven> if I'm not mistaken. 如果我没有记错的话,您想通过@Transactional增强的组件必须与<tx:annotation-driven>处于同一上下文中。 So the @Transactional does not work. 因此,@ Transactional无法正常工作。

That was my silly mistake. 那是我愚蠢的错误。 The Spring uses CGLIB to proxy methods with @Transactional annotated and it seems like CBLIB can't enhance protected method. Spring使用CGLIB代理带有@Transactional注释的方法,似乎CBLIB无法增强受保护的方法。

protected String home() {

Changing this to 更改为

public String home() {

fixed the problem. 解决了问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM