Foi 6.1, JPA com JTA, Hibernate, Spring: Data Retrieval Problem
-
13-09-2019 - |
Pergunta
Estou executando um aplicativo com os seguintes componentes:
- Oracle 9i
- Foi 6.1.0.23 com pacote de recursos ws e ejb3
- JPA com Hibernate 3.3.2.Ga como provedor (com Hibernate-IntityManager 3.4.0)
- Spring Transaction Manager for: UowtransactionManager (Spring 2.5.6)
- Spring Webflow com persistência gerenciada por fluxo (2.0.8), ou seja, o gerente de entidade é serializado na sessão HTTP e restaurado em cada solicitação.
Em cada solicitação que vai do controlador da web para a camada de serviço (anotada com o @Transactional de Spring), notei que, para cada consulta SQL que o Hibernate realiza durante a invocação de serviço dentro da transação, uma nova conexão com dados de dados é solicitada ao conjunto de dados JNDI por meio O ConnectionProvider da Hibernate, até que a fonte de dados fique sem conexões gratuitas e eventualmente pendure.
Aqui estão partes da configuração:
Primavera:
<tx:annotation-driven /> <context:component-scan base-package="org.home.myapp" /> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/DS" resource-ref="true"/> <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/> <bean id="EMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> </bean>
persistence.xml
<persistence-unit name="persistence" transaction-type="JTA"> <properties> <property name="hibernate.archive.autodetection" value="class"/> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect"/> <property name="hibernate.current_session_context_class" value="jta"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.default_batch_fetch_size" value="20"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/> </properties> </persistence-unit>
Serviço
@Transactional(readOnly=true) @Service public class MyServiceImpl implements MyService { @Autowired MyDao dao; public void getSomething() { dao.findSomething(); } }
Dao
@Repository public class MyDaoJap implements MyDao { @PersistenceContext EntityManager em; public void findSomething() { em.find(...); } }
Nota A transação é somente leitura, o que é normal para a persistência de fluxo: apenas a última transição (com commit = true) chama um método transacional não readonamente. Ligar o sinalizador readonly gira automaticamente o modo de descarga de hibernação para manual.
Enquanto fazia alguma depuração, notei o seguinte:
- O gerente de transação da UOW é invocado corretamente na cadeia de interceptação do serviço, o que sugere que uma transação está ativa
- O Hibernate solicita uma conexão invocando DataSource.getConnection () na fonte de dados bruta que é injetada no EMF; A estratégia para obter uma conexão é do injeção de hibernateDataSourceConnectionProvider, e essa classe faz referência ao DataSource (não é um proxy que está ciente de uma transação ativa ou tal).
Acho que o problema está neste segundo ponto, mas não consigo encontrar um erro na minha configuração. Alguém pode ajudar?
Obrigado pela ajuda.
Solução
Algumas suposições selvagens da nossa configuração
- hibernate prop - hibernate.connection.release_mode = pós -estatamento
- Web.xml Recurso Ref DataSource Config -u003Cres-sharing-scope> Compartilhávelu003C/res-sharing-scope>
- Spring SessionFactory Config - USETransactionAwaredataSource = "true"
até pode ser uma questão de configuração dentro de
Outras dicas
Penso (e espero) que seus problemas decorrem do fato de que, ao usar a propriedade DataSource, isso é padronizado para uma "não jtadataSource". A configuração padrão (simples) é realmente otimizada para sistemas transacionais de menor grau (Tomcat/SE) e não a pilha mais hardcore que você está usando.
Você precisará configurar a fábrica do Entity Manager para ter um conjunto de dados JTA. A maneira como fiz isso é criar meu próprio jTaperSistenceUnitPostProcessor, onde eu poderia configurar isso.
Ao fazê -lo dessa maneira, pude definir a EMF para usar uma JTadataSource, não tenho certeza se existe uma maneira melhor de fazer isso. Você pode simplesmente, como um POC adicionar a referência de DataSource do JTA à sua persistência.xml.