【问题标题】:Why is Spring's Transaction Management not working with this configuration?为什么 Spring 的事务管理不适用于此配置?
【发布时间】:2013-01-09 00:06:20
【问题描述】:

在 SO 上有很多关于此的问题,但我尝试了其中一些听起来正确的问题,但我仍然得到 ​​p>

org.hibernate.HibernateException: No Session found for current thread

我的服务层类是这样注释的:

   @Service
   public class MyService {
       @Autowired
       public SomeDao someDao;

       @Transactional
       public void performSomeTransaction() {/* ... */}
   }

我的应用程序上下文 XML 有以下相关声明:

    <context:component-scan base-package = "com.myapp.business.dao.impl" />
    <context:component-scan base-package = "com.myapp.business.services" />

    <context:annotation-config />

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

    <!-- Hibernate -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="hibernateProperties">
            <props>
                <prop key="connection.url">jdbc:mysql://localhost:3306/bidapp</prop>
                <prop key="connection.username">bidapp</prop>
                <prop key="connection.password">pennyfss</prop>
                <prop key="connection.driver_class">com.mysql.jdbc.Driver</prop>

                <prop key="hibernate.connection.pool_size">10</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>

                <prop key="c3p0.acquireIncrement">1</prop>
                <prop key="c3p0.max_size">50</prop>
                <prop key="c3p0.max_statement">0</prop>
                <prop key="c3p0.min_size">10</prop>
                <prop key="c3p0.timeout">0</prop>
            </props>
        </property>
        <property name="dataSource" ref="dataSource"></property>
        <property name="packagesToScan">
            <list>
                <value>com.bidapp.business.domain</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/bidapp" />
        <property name="username" value="bidapp" />
        <property name="password" value="pennyfss" />
    </bean>

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

我也有我的dispatcher-servlet.xml 文件

    <mvc:annotation-driven />
<mvc:default-servlet-handler />

<context:component-scan base-package="com.myapp.presentation.controllers" />
<context:annotation-config />

<bean id="viewResolver" class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
    <property name="templateEngine" ref="templateEngine" />
</bean>

为什么 spring 不使用事务包装我的服务?

因此,问题似乎与未正确获取实例有关。我有以下 Shiro 安全配置:

    <bean id = "hibernateRealm" class = "com.bidapp.presentation.shiro.HibernateRealm" >
        <property name = "credentialsMatcher" ref = "credentialsMatcher" />
    </bean> 

    <bean id = "credentialsMatcher" class = "com.bidapp.presentation.shiro.JasyptCredentialsMatcher" />

    <bean id = "securityManager" class = "org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name = "realm" ref = "hibernateRealm" />
    </bean>

HibernateRealm 是带有@Transactional 注释的服务类。 Spring 不应该将它包装在代理中,因为它是在这里创建的。

【问题讨论】:

    标签: java spring hibernate spring-transactions


    【解决方案1】:

    此问题的最常见原因是

    1. 错误地获取服务实例:例如,自己实例化它而不是从 Spring 获取实例。
    2. 在 Spring MVC 应用程序中错误地配置了根应用程序上下文和子应用程序上下文。我在这里回答了很多这样的问题。以下是一些更具教育意义的:

    Spring XML file configuration hierarchy help/explanation

    Declaring Spring Bean in Parent Context vs Child Context

    显示获取和使用服务实例的代码将有助于定义问题。

    【讨论】:

    • 我很确定它与 1 有关。我正在使用 shiro 安全性并声明一个 bean 服务以在其中一个安全管理器中引用。有解决办法吗?
    • 我在我的 Realm 类中注入了一个 DAO。根据您的指示,我自动装配了一个调用 DAO 的服务类。它带有事务性注释,因此我得到了相同的行为,但需要额外的一跳。没什么大不了的。它有效。
    【解决方案2】:

    在 hibernate-persistance.xml 文件中创建会话工厂期间添加属性 hibernate.current_session_context_class=thread 它将起作用。

    【讨论】:

    • 你能补充一些关于为什么这个工作的更多信息,并可能在上下文中添加一个例子吗?
    • 这是因为一旦你添加了这个属性 hibernate.current_session_context_class=thread 你是说当 sessionFactory.getCurrentSession() 被调用时休眠给我一个绑定到每个线程的会话对象。这是我们需要在创建 sessionFactory 期间提供的,我们使用 sessionFactory 作为 TransactionManager Bean 中的依赖项来管理我们的事务。spring 会在一次线程中创建 transactionalProxy。
    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 1970-01-01
    • 2014-02-22
    • 2010-10-18
    • 2011-07-05
    • 1970-01-01
    相关资源
    最近更新 更多