Transações JpaTransactionManager não usadas pela sessão do Hibernate

Estou trabalhando em um projeto que está usando a estrutura Spring (4.3.3.RELEASE) e o Hibernate (5.2.3.Final) e estou começando a avançar para o uso do Spring Data JPA.

Acabei de migrar oLocalSessionFactoryBean comHibernateTransactionManager configuração para usar a configuração JPA deLocalContainerEntityManagerFactoryBean comJpaTransactionManager comHibernateJpaSessionFactoryBean.

O código de hibernação existente que usaSessions deSessionFactorys pareceu funcionar bem até que eu testei algum código que salva uma entidade e, em seguida, executa algumas consultas de atualização na mesma transação e o código falhou no sql de atualização com:

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

Os logs do gerenciador de transações mostraram que a transação estava ativa e depois revertida, o que era estranho. Percebi então que a operação de salvar havia atingido o banco de dados.

Na depuração, posso ver que o objeto de sessão não parece ter nenhum objeto de transação, portanto, parece que a sessão de hibernação não está trabalhando ou usando o servidor configuradoJpaTransactionManager transações.

Quando configuro um gerenciador de transações adicionais (HibernateTransactionManager) marcado como o PrincipalPlatformTransactionManager o código então funciona.

Avançando, ao migrar o código para o Spring Data Jpa, desejarei usar algum código Dao baseado no Hibernate e algum repositório do Spring Data Jpa na mesma transação. Como posso obter a fábrica de sessões para usar oJpaTransactionManager?

ATUALIZAR:

Descobri agora que a configuração acima significa que a sessão não é liberada no banco de dados pelo gerenciador de transações, portanto, não funciona corretamente.

Também descobri que se eu injetar o EntityManager no meu Daos:

@PersistenceContext()
private EntityManager entityManager;

E use:

entityManager.unwrap( Session.class )

Em seguida, o código participa da transação corretamente. Mas se eu receber oSessionFactory (injetado na primavera ou desembrulhado doentityManagerFactoryou usandogetSessionFactory() do desembrulhadoSession) e liguegetCurrentSession() retorna um objeto de sessão diferente que não está conectado à transação.

Minha configuração:

    @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;
        }    
    }

questionAnswers(0)

yourAnswerToTheQuestion