目录
步骤三:顺着源代码看 jdbcTemplate.queryForStream
使用 JdbcTemplate+dbcp连接池进行数据库访问
dbcp配置最大连接为10
- @Bean
- public BasicDataSource dataSource() {
- BasicDataSource ds = new BasicDataSource();
- ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
- ds.setUrl("jdbc:mysql://localhost:3306/xxx");
- ds.setUsername("root");
- ds.setPassword("xxxx");
- ds.setInitialSize(5);
- ds.setMaxTotal(10);
- return ds;
- }
JdbcTemplate配置为
- @Bean
- public JdbcTemplate jdbcTemplate(javax.sql.DataSource dataSource) {
- return new JdbcTemplate(dataSource);
- }
使用的代码为
- public List
selectByName() { - String sql = "select * from base_sku where sku_name like '%瓜';";
- Stream
baseSkuDOStream = jdbcTemplate.queryForStream(sql, new BaseSkuDoRowMapper()); - List
baseSkuDOs = baseSkuDOStream.collect(Collectors.toList()); - return baseSkuDOs;
- }
代码运行10次后,代码夯住,不能继续运行
发现一直卡在获取数据库连接处,表明获取不到数据库连接,怀疑连接耗尽了
System.out.println("dbcp连接池可用连接:"+basicDataSource.getNumIdle()
打印结果:
dbcp连接池可用连接:0
的确被耗尽,所以推断是连接没有释放
在网上查询JdbcTemplate使用连接是自动释放的,无需手动释放
但这里的确没有归还
发现调用execute时,stream方法中传的关闭资源是false
也就是说 jdbcTemplate.queryForStream 这个方法不会自动关闭连接
所以应该需要手动close 资源
在代码中加入stream的close,运行果然能释放连接了
- public List
selectByName() { - String sql = "select * from base_sku where sku_name like '%瓜';";
- Stream
baseSkuDOStream = jdbcTemplate.queryForStream(sql, new BaseSkuDoRowMapper()); - List
baseSkuDOs = baseSkuDOStream.collect(Collectors.toList()); - //加入stream关闭
- baseSkuDOStream.close();
- return baseSkuDOs;
- }
所以猜这里的stream这种模式,是不会自动关闭的,看一下其他调用jdbcTemplate.execute的地方,果然,除了queryForStream方法
其他的都是可以自动关闭的,看来是遇到坑了,下次一定切记,jdbcTemplate 使用queryForStream方法一定要手动关闭连接。
遇到数据库连接相关问题以后可以按照此思路排查。