Не удалось получить сеанс, синхронизированный с транзакцией, для текущей ошибки потока в управлении транзакциями Spring

Я работаю над переносом приложения с Spring 3.2 на Spring 5. Приложение использует AWS RDS с основной базой данных в качестве основного или главного источника данных и репликой базы данных в качестве источника данных только для чтения. Приложение создает один экземпляр фабрики сеансов (primarySessionFacotry) для основного источника данных и еще один экземпляр (readOnlySessionFactory) для источника данных, доступного только для чтения, чтобы один и тот же DAO можно было использовать для обоих источников данных путем связывания каждой фабрики сеансов.

appContext-hibernate.xml

<bean id="primaryDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass">
        <value>com.mysql.jdbc.Driver</value>
    </property>
    <property name="jdbcUrl">
        <value>${database.jdbcurl}</value>
    </property>
    <property name="user">
        <value>${database.dbuser}</value>
    </property>
    <property name="password">
        <value>${database.dbpassword}</value>
    </property>

</bean>

<bean id="primarySessionFactory"
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="primaryDataSource"/>
    <property name="mappingResources" ref="hbmFileLocations">
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">${hibernate.showSQL}</prop>
            <prop key="hibernate.format_sql">${hibernate.formatSQL}</prop>
        </props>
    </property>
</bean>

<util:list id="hbmFileLocations" value-type="java.lang.String">
    <value>com/xxxx/yyyyy/persistence/mappings/users.hbm.xml</value>
</util:list>

<bean id="primaryTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="primarySessionFactory">
    </property>
</bean>

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

appContext-hibernate-ro.xml

<bean id="readOnlyDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass">
        <value>com.mysql.jdbc.Driver</value>
    </property>
    <property name="jdbcUrl">
        <value>${database.readonly.jdbcurl}</value>
    </property>
    <property name="user">
        <value>${database.readonly.dbuser}</value>
    </property>
    <property name="password">
        <value>${database.readonly.dbpassword}</value>
    </property>
    
</bean>

<bean id="readOnlySessionFactory"
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="readOnlyDataSource"/>
    <property name="mappingResources" ref="hbmFileLocations">
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">${hibernate.readonly.showSQL}</prop>
            <prop key="hibernate.format_sql">${hibernate.readonly.formatSQL}</prop>
        </props>
    </property>

</bean>

<bean id="readOnlyTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="readOnlySessionFactory"/>
</bean>

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

DAO создаются следующим образом

<bean id="userDao" class="xxxxx.persistence.UserDao">
    <property name="sessionFactory" ref="primarySessionFactory"/>
</bean>
<bean id="readOnlyUserDao" class="xxxxx.persistence.UserDao">
    <property name="sessionFactory" ref="readOnlySessionFactory"/>
</bean>

Этот UserDao имеет метод, как показано ниже

@Transactional
public List<User> getItems()
{
    return sessionFactory.getCurrentSession().createQuery("from User user where isDeleted=false").list();
}

Мы получаем исключение ниже при использовании метода UserDao.getItems() с экземпляром readOnlyUserDao.

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:143)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:497)

Обратите внимание, что этот же код отлично работает с Spring ( spring-orm и spring-tx 3.2)

Пожалуйста, помогите решить это.


person mambo    schedule 13.03.2021    source источник
comment
какую версию весны вы здесь пытаетесь ... Хотя я получаю то же исключение, когда использую пружину 5.3.4, но не в версии весны 5.1.12.   -  person ragul rangarajan    schedule 18.03.2021
comment
Я переносил весну 3.2 на 5.1.x. К счастью, у меня есть решение проблемы, и я собираюсь опубликовать решение в отдельном комментарии.   -  person mambo    schedule 19.03.2021
comment
Отлично .. что у вас есть решение. Поделитесь своим решением здесь, чтобы оно было полезно для всех.   -  person ragul rangarajan    schedule 22.03.2021


Ответы (1)


У меня была такая же проблема, и я выполнил шаг, упомянутый здесь, и он отлично подходит для моего случая. Spring Hibernate - не удалось получить сеанс, синхронизированный с транзакциями, для текущего тема

Session session;
try {
    session = sessionFactory.getCurrentSession();
} catch (HibernateException e) {
    session = sessionFactory.openSession();
}
return session;
person ragul rangarajan    schedule 18.03.2021
comment
Спасибо за ваш ответ Рагул Рангараджан. Это потребует изменения кода для каждого метода, который у нас есть, а их тысячи. Я нашел другое решение для своей проблемы и опубликую его в отдельном комментарии. - person mambo; 19.03.2021