【问题标题】:DB connections not closing in OSGi数据库连接未在 OSGi 中关闭
【发布时间】:2013-10-13 16:35:14
【问题描述】:

我有一个 OSGi 包,它需要将数据保存在数据库中。如in a previous stackoverflow question 所述,我发现为了使事务按预期工作,我需要使用 XADataSource 连接到数据库。但是,当我这样做时,我发现我的应用程序打开的与数据库的连接永远不会关闭,这当然会导致数据库在一段时间后无法接受更多的连接。

我的设置如下:

我有一个创建数据源的包,它只包含一个带有以下内容的 blueprint.xml 文件

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
      <property name="url" value="jdbc:mysql://localhost:3306/myschema"/>
      <property name="user" value="user"/>
      <property name="password" value="pass"/>
  </bean>

  <service interface="javax.sql.XADataSource" ref="dataSource">
    <service-properties>
            <entry key="osgi.jndi.service.name" value="jdbc/mysqlds"/>
    </service-properties>
  </service>
</blueprint>

然后在持久化我的数据的包中,我有一个 persistence.xml

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="mypu" transaction-type="JTA">
        <jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/mysqlds)
        </jta-data-source>
    </persistence-unit>

</persistence>

我指定我的服务方法应该在我的 blueprint.xml 中的事务中运行

<bean id="MyServiceImpl"
          class="com.test.impl.MyServiceImpl">
    <jpa:context property="em" unitname="mypu" />
    <tx:transaction method="*" value="Required" />
</bean>
<service id="MyService" ref="MyServiceImpl" interface="com.test.api.MyService" /> 

我在 Karaf 中通过包部署,使用 Aries 和 OpenJPA 进行持久性,同时我还部署了 Aries 事务包装包 (org.apache.aries.transaction.wrappers) 以便将我的 XA 资源加入事务管理器。

任何想法我在我的配置中缺少什么?

编辑: 经过更多搜索后,我找到了this DBCP issue,这表明我遇到的问题是 MySQL 的 DBCP 错误。但是,我不知道如何用 OpenJPA 可以使用的其他一些连接池实现替换 DBCP。任何建议都非常受欢迎。

【问题讨论】:

    标签: osgi database-connection openjpa apache-commons-dbcp aries


    【解决方案1】:

    我使用 commons-dbcp 建立了一个连接池,该连接池还使用以下配置登记 XA 连接:

    <bean id="myXAEnabledConnectionPoolDataSource" class="org.apache.commons.dbcp.managed.BasicManagedDataSource" destroy-method="close">
        <property name="xaDataSourceInstance" ref="mysqlXADataSourceBean" />
        <property name="transactionManager" ref="transactionManager" />
    </bean>
    

    可以根据接口javax.transaction.TransactionManager获取事务管理器作为参考。

    通过这种方式,commons-dbcp 将正确处理连接的生命周期。请注意,destroy方法是存在的,所以当蓝图容器停止时,连接池将被关闭。

    编辑:

    1-2 年前我遇到了同样的问题,但使用的是 PostgreSQL。我当时调试了 aries.transaction.wrapper 很多,但我不记得确切的原因为什么我把它遗漏了。我认为 commons-dbcp 是一个在以前的项目中为我工作的解决方案背后的动机,而即使在分析了很多代码之后我也无法修复 aries.transaction.wrapper。

    请注意,MysqlDataSource 不是连接池。它总是在您需要时返回一个新的连接。它也没有启用 XA。 MysqlXADatasource 已启用 XA,因此您可能应该从该类实例化一个对象。但是,XADataSource 只负责为您返回 XAConnections,而不负责征用它们。这就是 ManagedConnectionPool 可以提供帮助的地方。托管连接池执行以下操作:

    • 使用自定义托管连接类包装所有提供的 Connection 对象
    • 如果在连接上调用关闭,如果有正在进行的事务,它不会关闭。只有在事务提交或回滚完成时才会关闭(添加回池中)
    • 如果从池中查询了一个连接,并且在同一个事务中也提供了一个连接,则将返回相同的事务(这是一个困难的句子:))

    有时 JDBC 驱动程序提供连接池甚至托管连接池,但是,最好只使用 JDBC 驱动程序来获取新连接并将其包装在经过多个项目测试并且可以肯定工作的 3rdparty 库中。

    【讨论】:

    • 谢谢巴拉兹。我试过你的建议,到目前为止它似乎有效。你认为你能解释一下为什么这个配置可以解决这个问题吗?
    猜你喜欢
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 2012-07-12
    • 2011-01-14
    相关资源
    最近更新 更多