Транзакции JpaTransactionManager не используются Hibernate Session

Я работаю над проектом, который использует Spring Framework (4.3.3.RELEASE) и Hibernate (5.2.3.Final), и я начинаю переходить на использование Spring Data JPA.

Я только что перенесLocalSessionFactoryBean сHibernateTransactionManager Конфигурация с использованием конфигурации JPALocalContainerEntityManagerFactoryBean сJpaTransactionManager сHibernateJpaSessionFactoryBean.

Существующий код гибернации, который используетSessionс изSessionFactoryКазалось, что все работает нормально, пока я не протестировал некоторый код, который сохраняет одну сущность, а затем запускает несколько запросов на обновление в той же транзакции, и код завершается ошибкой при обновлении sql с помощью:

javax.persistence.TransactionRequiredException: Executing an update/delete query

Журналы менеджера транзакций показали, что транзакция была активной, а затем откат, что было странно. Затем я заметил, что операция сохранения достигла базы данных.

При отладке я вижу, что у объекта сеанса, похоже, нет объекта транзакции, поэтому кажется, что сеанс гибернации не работает или не использует настроенныйJpaTransactionManager сделки.

Когда я настраиваю дополнительный менеджер транзакций (HibernateTransactionManager) помечены как первичныеPlatformTransactionManager код тогда работает.

В дальнейшем, когда я перенесу код в Spring Data Jpa, я захочу использовать некоторый код Dao на основе Hibernate и некоторый репозиторий Spring Data Jpa в одной и той же транзакции. Как я могу заставить фабрику сеансов использоватьJpaTransactionManager?

ОБНОВИТЬ:

Теперь я обнаружил, что вышеуказанный конфиг означает, что сессия не сбрасывается в базу данных менеджером транзакций, поэтому не работает правильно.

Я также обнаружил, что если я добавлю EntityManager в мой Daos:

@PersistenceContext()
private EntityManager entityManager;

и использовать:

entityManager.unwrap( Session.class )

Тогда код правильно участвует в транзакции. Но если я получуSessionFactory (либо вводится весной, либо распаковывается изentityManagerFactoryили используяgetSessionFactory() из развернутогоSession) и позвонитеgetCurrentSession() он возвращает другой объект Session, который не связан с транзакцией.

Моя конфигурация:

    @Configuration
    @EnableJpaRepositories(
            basePackages = "com.mycompany.common.services",
            transactionManagerRef = "jpaTransactionManager"
    )
    @EnableTransactionManagement(order = 5)
    public class PersistenceConfiguration
    {
        @Bean
        @Qualifier(value = "entityManagerFactory")
        public LocalContainerEntityManagerFactoryBean entityManagerFactory( DataSource dataSource )
        {
            LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
            factory.setPersistenceUnitName( "entityManagerFactory" );
            factory.setPackagesToScan( entityPackages() );
            factory.setJpaVendorAdapter( getHibernateJpaVendorAdapter() );
            factory.setJpaProperties( getJpaProperties() );
            factory.setDataSource( dataSource );
            factory.afterPropertiesSet();

            return factory;
        }

        @Bean
        @Qualifier(value = "jpaTransactionManager")
        public PlatformTransactionManager jpaTransactionManager( EntityManagerFactory entityManagerFactory, DataSource dataSource )
        {
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory( entityManagerFactory );
            txManager.setDataSource( dataSource );
            return txManager;
        }


        @Bean
        @Qualifier(value = "sessionFactory")
        public FactoryBean<SessionFactory> sessionFactory( EntityManagerFactory entityManagerFactory )
        {
            HibernateJpaSessionFactoryBean hibernateJpaSessionFactoryBean = new HibernateJpaSessionFactoryBean();
            hibernateJpaSessionFactoryBean.setEntityManagerFactory( entityManagerFactory );
            return hibernateJpaSessionFactoryBean;
        }

        // How do I remove this and just use the one transaction manager above?   
/*
        @Bean
        @Qualifier(value = "hibernateTransactionManager")
        @Primary
        public PlatformTransactionManager hibernateTransactionManager( SessionFactory sessionFactory )
        {
            HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager( sessionFactory );
            return hibernateTransactionManager;
        }    
*/        
        @Bean
        public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
        {
            return new PersistenceExceptionTranslationPostProcessor();
        }

        protected HibernateJpaVendorAdapter getHibernateJpaVendorAdapter()
        {
            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setGenerateDdl( isGenerateDDL() );
            vendorAdapter.setDatabase( Database.MYSQL );
            vendorAdapter.setDatabasePlatform( com.mycompany.common.utils.hibernate.MySQL56InnoDBDialect.class.getName() );
            return vendorAdapter;
        }

        protected Properties getJpaProperties()
        {
            Properties properties = new Properties();
            properties.put("hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");
            properties.put("hibernate.hbm2ddl.auto", "validate");
            properties.put("hibernate.transaction.flush_before_completion", "true");
            properties.put("hibernate.transaction.auto_close_session", "false");
            properties.put("hibernate.use_outer_join", "true");

            properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
            properties.put("hibernate.cache.use_second_level_cache", "true");
            properties.put("net.sf.ehcache.configurationResourceName", "META-INF/resources/ehcache-hibernate.xml");
            properties.put("hibernate.cache.use_query_cache", "true");
            properties.put("hibernate.jdbc.batch_size", "100");

            properties.put("hibernate.generate_statistics", "true");
            properties.put("hibernate.format_sql", "true");
            properties.put("hibernate.use_sql_comments", "true");
            properties.put("org.hibernate.SQL", "info");

            return properties;
        }

        protected boolean isGenerateDDL()
        {
            return false;
        }    
    }

Ответы на вопрос(0)

Ваш ответ на вопрос