【问题标题】:HikariCP without Framework无框架的 HikariCP
【发布时间】:2016-07-11 08:08:23
【问题描述】:

我是第一次在 Java 中使用 HikariCP,但没有使用任何后端框架或 JPA。

我的项目有以下包结构

----db
----controllers
----views
----models
----handlers

db.DBManager.java 是设置 hikari 数据源的位置:

public class DBManager {
final protected HikariDataSource hikariDS;
protected Connection connection = null;

public DBManager() {

    String resourceName = "re/iprocu/coperativeerp/config/db/dbSettings.properties"; // could also be a constant
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    Properties props = new Properties();
    try(InputStream resourceStream = loader.getResourceAsStream(resourceName)) {
        props.load(resourceStream);
    } catch (IOException ex) {
        Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, ex);
    }
    final HikariConfig hikariConfig = new  HikariConfig(props);
    //hikariConfig.setConnectionInitSql(absoluteFilePath);
    hikariConfig.setMaximumPoolSize(30);
    hikariConfig.setMinimumIdle(10);
    hikariConfig.setPoolName("TripPool");
    hikariConfig.setConnectionTimeout(1000);
    hikariConfig.setConnectionTestQuery("SELECT 1");
    hikariConfig.setAutoCommit(true);
    hikariConfig.setInitializationFailFast(false);
    hikariConfig.setLeakDetectionThreshold(2000);
    this.hikariDS = new HikariDataSource(hikariConfig);
}
}

handlerspackage 是对 db 进行查询的地方。 处理程序类扩展 DBManager 以获取初始化的 hikari 数据源。

package re.iprocu.coperativeerp.handlers;
public class InventoryHandler extends DBManager{

   final static private Logger logger = Logger.getLogger(SupplierHandler.class.getName());

public InventoryHandler(){
    super();
} 


public int addProductToInventory(Inventory inv){
    int key = 0;

    PreparedStatement ps = null;
    try{
        connection  = hikariDS.getConnection();
        ps = connection.prepareStatement(sql);

        ps.executeUpdate();

        generatedKeys = ps.getGeneratedKeys();
        if (generatedKeys != null && generatedKeys.next()) {
            key = generatedKeys.getInt(1);
        } else {
            System.out.println("No Key");
        }
    }catch(SQLException e){ e.printStackTrace();}
    finally{
        if( connection != null ){
            try {connection.close();} 
            catch (SQLException ex) {logger.log(Level.SEVERE, null, ex);}
        }
        if( ps != null){
            try { ps.close();} 
            catch (SQLException ex) { logger.log(Level.SEVERE, null, ex);}
        }
    }

    return key;
}
}

controllerspackage 我定义和初始化我需要使用的处理程序,并调用相应的方法。

问题是在刷新 ui 或有时第一次加载后,抛出错误java.sql.SQLTransientConnectionException: TripPool - Connection is not available, request timed out after 1001ms.

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"

根据我的项目结构,我配置 HikariCP 并最大限度地利用它的最佳方式是什么

编辑:

我发现这个 stackoverflow Question 它对我有用,尽管我担心解决方案有一个 Double-checked locking 问题在讨论中没有解决,我不知道该怎么做

【问题讨论】:

  • Hikari 有多少个实例?你用的是什么网络服务器?
  • 已安装 XAMPP,因此使用 Apache....我该如何维护它?
  • 您创建的每个类实例都会重新创建数据源,基本上每次添加 10 个连接。您应该创建一次 DataSource 并在整个应用程序中重复使用。
  • 哇!脑洞大开……
  • 我更新了一个指向 stackoverflow 问题的链接,该问题执行此操作,维护一个 DataSource 实例...尽管根据接受的答案可能会出现Double-checked locking 问题,我仍然不知道如何解决解决...可以吗?

标签: java mysql hikaricp


【解决方案1】:

您的错误消息显示,您的数据库当前打开的连接过多。所以首先你可以查阅你的数据库文档并增加连接限制。或者与您的数据库管理员交谈,如果您有的话。

可能的原因是您为DBManager 的任何子类的每个新实例创建了新数据源。将您的 hikariDS 设为静态字段并在静态块中对其进行初始化:

public class DBManager {
  public static final HikariDataSource hikariDS;

  static {
    String resourceName = "re/iprocu/coperativeerp/config/db/dbSettings.properties";
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    Properties props = new Properties();
    try(InputStream resourceStream = loader.getResourceAsStream(resourceName)) {
      props.load(resourceStream);
    } catch (IOException ex) {
      Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, ex);
    }

    final HikariConfig hikariConfig = new  HikariConfig(props);
    hikariConfig.setMaximumPoolSize(30);
    hikariConfig.setMinimumIdle(10);
    hikariConfig.setPoolName("TripPool");
    hikariConfig.setConnectionTimeout(1000);
    hikariConfig.setConnectionTestQuery("SELECT 1");
    hikariConfig.setAutoCommit(true);
    hikariConfig.setInitializationFailFast(false);
    hikariConfig.setLeakDetectionThreshold(2000);
    DBManager.hikariDS = new HikariDataSource(hikariConfig);
  }
}

我还删除了connection 字段。您最好将其存储在方法的局部变量中。

【讨论】:

  • 没有数据库管理员,只有我...缩小连接池并不能解决问题。我想这可能是我创建池本身的方式?在那方面有什么建议吗?
  • 对我来说似乎没问题...您是否尝试过增加数据库中的连接限制
  • 正如 M. Deinum 评论所说,连接过多的问题是因为我创建了许多 HikariDataSource 实例,每次创建时都会添加 10 个连接。
  • 我更新了一个指向 stackoverflow 问题的链接,该问题执行此操作,维护 DataSource 的一个实例......尽管根据接受的答案,可能会出现双重检查锁定问题,我仍然不知道如何解决...可以吗?
  • @YunusEinsteinium 我已经更新了我的答案。我相信我现在明白了你的麻烦的真正根本原因:)
猜你喜欢
  • 1970-01-01
  • 2015-07-31
  • 2021-08-07
  • 1970-01-01
  • 2017-11-09
  • 1970-01-01
  • 2015-02-11
  • 2017-11-29
  • 2016-06-20
相关资源
最近更新 更多