【问题标题】:Too many connections spring boot jdbc太多的连接spring boot jdbc
【发布时间】:2016-08-14 08:33:23
【问题描述】:

我知道这将是重复的问题,但我觉得我的问题有点不同。

我有 JdbcDAO 类,例如

    @Component
    public class JdbcUserDAO implements UserDAO {
    @Autowired
    MyJdbc myJdbc;
   }

我已将 MyJdbc 类定义如下:

@Component
public class MyJdbc {

@Autowired
    protected JdbcTemplate jdbc;

}

在 MyJdbc 类中,我定义了 insert 和 batchupdate 并通过 jdbc 变量调用它们。 会不会造成过多的连接异常。

我已经在 application.properties 文件中定义了 jdbc 参数:

spring.datasource.url=#databaseurl
spring.datasource.username=#username
spring.datasource.password=#password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.test-on-borrow=true
spring.datasource.max-active=100
spring.datasource.max-wait=10000
spring.datasource.min-idle=10
spring.datasource.validation-query=SELECT 1
spring.datasource.time-between-eviction-runs-millis= 5000
spring.datasource.min-evictable-idle-time-millis=30000
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.test-on-return=false

我遇到了异常:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Too many connections

我对各种常量的 application.properties 文件进行了许多更改,但没有奏效。我的数据库托管在 AWS RDS 上。

但是为了更新 blob 图像值,我会这样做:

blob= myJdbc.jdbc.getDataSource().getConnection().createBlob();
            blob.setBytes(1, str.getBytes());
            pstmt = myJdbc.jdbc.getDataSource().getConnection().prepareStatement("update user_profile set profileImage=? where user_profile.id in ( select id from user_login where email=?)");

【问题讨论】:

  • 错误来自MySQL,而不是您的应用程序,您知道您的RDS实例能够处理多少个连接吗?我的猜测是小于 100。
  • 你有什么理由使用纯 Jdbc API 而不是 Spring Data 或 JPA?
  • @DaveBower :我确实显示了像“max_connections”这样的全局变量;它显示 66
  • 优先使用JdbcTemplate#execute(ConnectionCallback<T>)在连接中执行sql语句。 myJdbc.jdbc.getDataSource().getConnection() 不安全,因为它可能会干扰现有事务,并且您必须在使用后关闭连接。
  • 您的代码有缺陷。它在 Spring 管理的连接旁边打开 2 个附加连接。永远不会获得这样的连接?将代码包装在ConnectionCallback 中,如果您确实需要连接,请不要尝试自己获取!

标签: spring amazon-web-services jdbc spring-boot


【解决方案1】:
blob= myJdbc.jdbc.getDataSource().getConnection().createBlob();
blob.setBytes(1, str.getBytes());
pstmt = myJdbc.jdbc.getDataSource().getConnection().prepareStatement("update user_profile set profileImage=? where user_profile.id in ( select id from user_login where email=?)");

问题在于您的代码。该代码打开 2 个与数据库的附加连接,而不关闭它们。您自己打开连接,然后您也应该关闭它们。但是,在这些情况下最好使用ConnectionCallback

myJdbc.execute(new ConnectionCallback() {
    public Object doInConnection(Connection con) throws SQLException, DataAccessException {
        blob = con.createBlob();
        blob.setBytes(1, str.getBytes());
       pstmt = con.prepareStatement("update user_profile set profileImage=? where user_profile.id in ( select id from user_login where email=?)");
       return null;
    }
});

然而,使用 Spring JDBCs Blob 支持更加容易(参见the reference guide)。这样你就不需要自己弄乱连接和blob了。

final String query = "update user_profile set profileImage=? where user_profile.id in ( select id from user_login where email=?)";
myJdbc.jdbc.execute(query, new AbstractLobCreatingPreparedStatementCallback(lobHandler) { 1
    protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException {
        byte[] bytes = str.getBytes();
        ps.setString(2, email);
        lobCreator.setBlobAsBinaryStream(ps, 1, str.getBytes()); 
    }
});

【讨论】:

  • 我会试试这个,但我是在使用我自定义的 DAO 类来查询它是正确的方式还是同时打开了多个连接。
  • 使用 jdbc 模板...你自己做getCOnnection 的每个地方(基本上绕过spring 及其事务和资源管理)你都在自己管理连接。正确使用 JdbcTemplate。使用不在它周围的框架。
  • 如 JDBC blob 支持中所见,如何读回 blob 的存储值并转换回字符串。
猜你喜欢
  • 2014-07-22
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
相关资源
最近更新 更多