WAS 6.1、JPA 与 JTA、Hibernate、Spring:数据检索问题

发布于 2024-08-14 08:17:42 字数 2724 浏览 6 评论 0原文

我正在运行具有以下组件的应用程序:

  • Oracle 9i
  • WAS 6.1.0.23,带有 WS 和 EJB3 功能包
  • JPA,以 Hibernate 3.3.2.GA 作为提供程序(带有 Hibernate-EntityManager 3.4.0)
  • WAS 的 Spring 事务管理器: UowTransactionManager ( spring 2.5.6)
  • Spring webflow 具有流管理持久性 (2.0.8),即实体管理器被序列化到 http 会话中,并在每个请求时恢复。

在从 Web 控制器到服务层(用 Spring 的 @Transactional 注释)的每个请求中,我注意到对于 Hibernate 在事务内的服务调用期间执行的每个 SQL 查询,都会从 jndi DataSource 请求一个新的 DataSource 连接: Hibernate 的 ConnectionProvider,直到 DataSource 用完可用连接并最终挂起。

以下是部分配置:

  1. Spring:

    >
    
    
    />
    
      <属性名称=“数据源”ref=“数据源”/>
      <属性名称=“jpaVendorAdapter”>
        />
      
    
    
  2. persistence.xml

    
      <属性>
        <属性名称=“hibernate.archive.autodetection”值=“class”/>
        <属性名称=“hibernate.dialect”值=“org.hibernate.dialect.Oracle9iDialect”/>
        <属性名称=“hibernate.current_session_context_class”值=“jta”/>
        <属性名称=“hibernate.cache.provider_class”值=“org.hibernate.cache.NoCacheProvider”/>
        <属性名称=“hibernate.format_sql”值=“true”/>
        <属性名称=“hibernate.show_sql”值=“true”/>
        <属性名称=“hibernate.default_batch_fetch_size”值=“20”/>
        <属性名称=“hibernate.transaction.manager_lookup_class”值=“org.hibernate.transaction.WebSphereExtendedJTATransactionLookup”/>   
      
    
    
  3. 服务

    @Transactional(readOnly=true) @Service
    公共类 MyServiceImpl 实现 MyService {
      @Autowired MyDao dao;
      公共无效 getSomething() {
        dao.findSomething();
      }
    }
    
  4. DAO

    <前><代码>@Repository 公共类 MyDaoJap 实现 MyDao { @PersistenceContext EntityManager em; 公共无效findSomething(){ em.find(...); } }

请注意,事务是只读的,这对于流程持久性来说是正常的:只有最后一个转换(commit=true)才会调用非只读事务方法。打开 readOnly 标志会自动将 Hibernate 刷新模式更改为 MANUAL。

在进行一些调试时,我注意到以下内容:

  • UOW 事务管理器在服务的拦截链中被正确调用,这表明事务处于活动状态
  • Hibernate 通过在原始数据源上调用 DataSource.getConnection() 来请求连接,即注入EMF;获取连接的策略来自 Hibernate 的 InjectedDataSourceConnectionProvider,该类引用 WAS DataSource(不是了解活动事务的代理等)。

我猜问题出在第二点,但我在配置中找不到错误。有人可以帮忙吗?

感谢您的帮助。

I'm running an application with the following components:

  • Oracle 9i
  • WAS 6.1.0.23 with WS and EJB3 features pack
  • JPA with Hibernate 3.3.2.GA as provider (with Hibernate-EntityManager 3.4.0)
  • Spring transaction manager for WAS : UowTransactionManager (spring 2.5.6)
  • Spring webflow with flow-managed persistence (2.0.8), i.e. the entity manager is serialized into the http session, and restored on each request.

In each request going from the web controller to the service layer (annotated with Spring's @Transactional), I have noticed that for each SQL query that Hibernate performs during the service invocation inside the transaction, a new DataSource connnection is requested from the jndi DataSource by Hibernate's ConnectionProvider, until the DataSource runs out of free connections and eventually hangs.

Here are parts of the configuration:

  1. Spring:

    <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>
    
  2. 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>
    
  3. Service

    @Transactional(readOnly=true) @Service
    public class MyServiceImpl implements MyService {
      @Autowired MyDao dao;
      public void getSomething() {
        dao.findSomething();
      }
    }
    
  4. DAO

    @Repository
    public class MyDaoJap implements MyDao {
      @PersistenceContext EntityManager em;
      public void findSomething() {
        em.find(...);
      }
    }
    

Note the transaction is read-only, which is normal for flow-persistence: only the last transition (with commit=true) invokes a non-readOnly transactional method. Turning on the readOnly flag automatically turns Hibernate flush mode to MANUAL.

While doing some debug, I noticed the following:

  • The UOW transaction manager is correctly invoked in the interception chain of the service, which suggests that a transaction is active
  • Hibernate asks for a connection by invoking DataSource.getConnection() on the raw DataSource that is injected into the EMF; The strategy for getting a connection is from Hibernate's InjectedDataSourceConnectionProvider, and this class references the WAS DataSource (not a proxy that is aware of an active transaction, or such).

I guess the problem is in this second point, but I can't find an error in my configuration. Can anybody help ?

Thanks for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

星星的轨迹 2024-08-21 08:17:42

来自我们的配置 hibernate prop 的一些疯狂猜测

  • - hibernate.connection.release_mode=after_statement
  • web.xml 资源引用数据源配置 -Shareable
  • spring sessionFactory 配置 - useTransactionAwareDataSource="true"

它甚至可能是内部的配置问题

some wild guesses from our config

  • hibernate prop - hibernate.connection.release_mode=after_statement
  • web.xml resource ref datasource config - <res-sharing-scope>Shareable</res-sharing-scope>
  • spring sessionFactory config - useTransactionAwareDataSource="true"

it even might be a configuration issue inside was

屋檐 2024-08-21 08:17:42

我认为(并希望)您的问题源于这样一个事实:通过使用 dataSource 属性,它默认为“nonJtaDataSource”。默认(简单)配置确实针对较低级别的事务系统(tomcat/SE)进行了优化,而不是您正在使用的更核心的堆栈。

您将需要配置实体管理器工厂以拥有 jta 数据源。我这样做的方法是创建我自己的 JtaPersistenceUnitPostProcessor,我可以在其中进行设置。

通过这种方式,我能够将 EMF 设置为使用 JtaDatasource,我不确定是否有更好的方法来做到这一点。您可以简单地作为 POC 将 jta 数据源引用添加到 persistence.xml 中。

I think (and hope) that your problems stems from the fact that by using the dataSource property it defaults to a "nonJtaDataSource". The default (simple) configuration is really optimised for lower grade transactional systems (tomcat/SE) and not the more hardcore stack that you're using.

You're going to need to configure the entity manager factory to have a jta datasource. The way that I did this is to create my own JtaPersistenceUnitPostProcessor where I could set this up.

By doing it this way I was able to set the EMF to use a JtaDatasource, I'm not sure if there is a better way of doing this. You could simply, as a POC add the jta datasource reference to your persistence.xml.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文