当前位置: 首页 > 知识库问答 >
问题:

在OSGi中嵌入Derby,使用连接池创建多个连接

凌通
2023-03-14

我想创建一个类的实例,该类可以访问底层的嵌入式derby数据库,并使用声明性服务将该类传递给绑定到数据库包的每个包。

我在derby留档中看到,为多个线程共享一个连接有很多陷阱。所以我在考虑为我正在创建的类的每个实例创建一个连接。由于我只想要一种非常简单的方法来创建多个连接并管理它们,因此在这里使用“MiniConnectionPoolManager”似乎是一个不错的选择。derby的示例代码如下所示:

org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource dataSource = new org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource();
dataSource.setDatabaseName("c:/temp/testDB");
dataSource.setCreateDatabase("create");
MiniConnectionPoolManager poolMgr = new MiniConnectionPoolManager(dataSource, maxConnections);
...
Connection connection = poolMgr.getConnection();
...
connection.close();

但是留档并没有涵盖很多东西,而且我是使用数据库的初学者。我的问题是:

>

我应该何时关闭此连接?我不知道bundle(user)将使用新类多长时间,所以我应该将新创建的连接保存在一个私有全局变量中,并强制用户执行unregister类,然后关闭连接吗?或者,当我的数据库包被停用时,我应该关闭所有连接吗。

对于管理访问一个数据库的不同类,我们也非常感谢其他建议。提前谢谢你。

编辑:

只要应用程序在运行,我的数据库包中的主类就始终处于活动状态。是包请求一个新类的实例(执行数据库操作)来来去去去。而且,由于它将部署在嵌入式系统中,我只能使用占用空间小的应用程序

共有1个答案

空浩淼
2023-03-14

您应该在需要时从连接池获得连接,并尽快关闭连接。重用连接是连接池的工作,而不是你的。

换句话说:在停用消费者捆绑包之前,不要保持连接处于活动状态。

连接池通常实现数据源接口,您应该通过它使用池。在这种情况下,您可以轻松地替换池实现,而无需更改代码。E、 g:

@Component
public class MyComponent {

    // Connection pool based DataSource
    @Reference
    DataSource dataSource;

    public void myFunction() {
        try (Connection c = dataSource.getConnection()) {
            // Database operations
        } catch (SQLException e) {
            // TODO
        }
    }
}

当您发现自己多次重复相同的代码(获取连接、捕获SQLException)时,您可以编写一个接受功能接口的简单组件。例如:

@Component
@Service
public class SQLHelper {

    @Reference // This is a connection pool DataSource
    private DataSource dataSource;

    public <R> R execute(Callback<R> callback) {
        try (Connection c = dataSource.getConnection()) {
            return callback.call(c);
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        }
    }
}

您的功能界面如下所示:

public interface Callback<R> {

    R call(Connection connection);

}

您可以这样使用它:

sqlHelper.execute((Connection c) -> {
    // Do some stuff with the connection
});

使用事务

如果你想使用原子事务,我建议你应该使用org。阿帕奇。德比。jdbc。EmbeddedXADataSource和org。阿帕奇。平民dbcp。管理。来自commons dbcp的BasicManagedDataSource。之后,您可以通过JTA处理事务。

很难直接使用JTA API。您应该选择一个有助于传播事务的库。

基于声明性服务的小指南:

  • 将derby jar安装到OSGi容器

现在您已经拥有了编写代码的一切。您的组件类似于以下内容:

@Component
@Service
public class MyComponent {

    @Reference
    private DataSource dataSource;

    @Reference
    private TransactionHelper th;

    public void myFunction() {
        th.required(() -> {
            try (Connection c = dataSource.getConnection()) {
                // My SQL statements
            } catch (SQLException e) {
                // TODO
            }
        }
    }
 }

如果您不需要交易处理,您可以:

  • 使用标准的EmbeddedDataSource
  • 使用任何非事务性连接池
  • 跳过TransactionManager和TransactionHelper捆绑包的安装
  • 从代码中跳过TransactionHelper的使用

更复杂的指南(也负责模式创建和使用基于OO的查询)位于http://cookbook.everit.org/persistence/index.html.

更新

您不必为每个SQL语句获取连接。您应该获得一个连接,在“片刻”内执行尽可能多的SQL语句,然后在连接上调用close。

  • 如果您必须运行三个SQL语句,您应该请求连接,执行三个SQL语句,然后调用连接上的关闭
  • 如果您在从池中请求的同一函数中关闭请求的连接,您可能做得对。您可能会调用将连接作为参数传递的其他函数,但它们应该只使用它来运行SQL语句并返回。
  • 您不应该保持连接处于活动状态并等待另一个用户操作。这是连接池的工作。当您调用池提供的连接关闭时,连接不会在物理上关闭,而只会检索到池。
  • 您应该将连接对象保留在局部变量中。如果您为连接对象使用成员变量,您应该怀疑您的代码有问题(唯一的例外是如果您将Connection传递给一个存活时间很短的对象,并且该对象将连接保存在成员html" target="_blank">变量中以获得更简洁的代码)。
  • 请注意,如果您使用Java6或更早版本,您应该在最终块中关闭连接,以避免未关闭的连接。

MiniConnectionPoolManager对于嵌入式设备来说可能是一个很好的解决方案,因为它实际上是“迷你型”的。唯一的问题是它没有实现数据源接口,因此您的业务代码将直接使用MiniCPM类。通过这样做,如果您发现bug或以后需要更复杂的连接池,那么切换到其他连接池将更加困难。

如果您决定使用MiniCPM,我建议您编写一个实现DataSource的组件,并将getConnection()函数委托给MiniCPM实例。E、 g.:

@Component
@Service
public class MiniCPMDataSourceComponent implements DataSource {

    @Reference
    protected ConnectionPoolDataSource cpDataSource;

    private MiniConnectionPoolManager wrapped;

    @Activate
    public void activate() {
        this.wrapped = new MiniConnectionPoolManager(cpDataSource);
    }

    @Override
    public Connection getConnection() {
        return wrapped.getConnection();
    }

    @Override
    public Connection getConnection(String user, String password) {
        throw new UnsupportedOperationException();
    }

    @Deactivate
    public void deactivate() {
        wrapped.dispose();
    }
}

您可以使用诸如最大连接数和超时(MiniCPM支持)之类的配置可能性来装饰此组件。如果使用此组件提供的服务,则可以在不更改业务代码的情况下切换连接池。此外,您的业务捆绑包不会直接连接到MiniCPM。

 类似资料:
  • 我的web应用程序(将部署在tomcat上)需要一个嵌入式数据库来存储临时用户数据,以便更快地检索。我选择Apache Embedded Derby是因为它很容易嵌入到web应用程序中,而且是一个纯Java DB。 我还实现了连接池来检索连接。我在这里面临着两个关键的问题(显示塞子)。首先,我的应用程序一次不能有两个以上的活动连接。所以,我的应用程序挂断了。 其次,我不断发现另一个应用程序已经启动

  • 我了解到连池的实现是基于提供者的,所以SQL数据提供者的连池工作方式将不同于Oledb的连池。(参考文献:http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx)池的默认最大物理连接是100。如果我们有不同的连接字符串(或不同的字符串顺序,但相同的数据库)或不同的窗口身份(如果我们使用窗口身份验证),新的连接池将被创建。 请让我知道,如果你不清楚

  • 我有这个使用HikariCP连接池的代码: 我通过发出命令“Show Processlist”来监控mysql中的连接,我看到在行之后创建了100个连接: 。。。正在运行。我肯定这不是命中注定的,对吧?它应该在稍后执行pooledDataSource时创建连接。getConnection()。 我做错了什么?为什么它会立即创建100个连接??

  • 我使用具有以下设置的Hikary连接池: 在getConnection()之后,hikari尝试获取到实例的2个连接,但只将一个连接放在连接池中。我怎样才能修好它?hikari版本是

  • 无法使用C3P0创建Hibernate-JPA连接池。面对以下错误日志: 请求请提供一个解决方案如何创建连接池使用JPA在KARAF。

  • 问题内容: 我正在使用JSCH进行sftp文件上传。在当前状态下,每个线程都会在需要时打开和关闭连接。 是否可以在JSCH中使用连接池,以避免由于大量打开和关闭连接而导致的开销? 这是从线程内部调用的函数的示例 问题答案: 为此,我希望使用commons-pool。;)