连接池在Spring Boot中使用JdbcTemplate

时间:2016-12-12 17:30:12

标签: java spring spring-boot dao jdbctemplate

使用Spring Boot和JdbcNamedTemplate查询数据库时,我遇到连接池耗尽的问题。

它应该如何运作:

  1. 从外面获取请求,并提供有关如何建造房屋的一些参数。
  2. 根据收到的参数,使用一些REST端点和两个DAO来收集数据。
  3. 使用数据创建House对象并将其返回。
  4. 更多请求......
  5. 截至目前的工作原理:

    1. 请求很好。
    2. 来自REST端点的数据 - 好的。 DAO数据 - >对于有两个DAO的前50个请求,单击确定,之后不行。当其中一个DAO被禁用时,不会阻止任何连接。
    3. 建好50栋房屋后,休息将永远完成,最后没有窗户。
    4. 使其无法用于更多请求,因为它们只会超时。
    5. 当我调用端点超过50次(最大池大小)时,我得到此异常:

          com.atomikos.jdbc.AtomikosSQLException: Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
      

      在重新启动应用程序之前,它会保持这样状态。看起来我的DAO或配置有些不足,但我无法弄清楚是什么,尽管整天都在搜索。如果有人可以提供帮助,我将感激不尽。

      额外信息: 我没有注意到其他异常。 正确检索所有其他数据。 发送帮助。

      更新: 我做了一些实验: 这个应用程序使用了我之前没有提及的另一个dao,因为我忘了。 它的工作方式几乎相同,只是它连接到不同的数据库,所以它有一个单独的配置。它还利用了JdbcNamedTemplate,并使用@Qualifier来选择正确的。

      现在,我发现,解雇一个或另一个DAO将不再使用连接。所以问题是:和平共处的是什么?

      这是道。

          @Component
          public class WindowsDao {
      
              private static final String PARAM_1 = "param";
      
              private final String SELECT_ALL = ""
                      + " SELECT "
                      + "   STUFF "
                      + " FROM TABLE " 
                      + " WHERE "
                      + "     THING =:" + PARAM_1
                      + " WITH UR";
      
              @Autowired
              private NamedParameterJdbcTemplate myTemplate;
      
              public Optional<List<BottomDealerText>> getWindows(
                      final WindowsCode windowCode {
      
                  final MapSqlParameterSource queryParameters = new MapSqlParameterSource()
                          .addValue(PARAM_1, windowCode.getValue())
      
                  final Optional<List<Window>> windows;
                  try {
                      windows = Optional.of(myTemplate.query(
                              SELECT_ALL,
                              queryParameters,
                              new WindowsRowMapper()));
                  }
                  catch (final EmptyResultDataAccessException e) {
                      LOG.warn("No results were found.");
                      return Optional.empty();
                  }
                  return windows;
              }
          }
      

      从此服务调用DAO:

          @Service
          @Transactional
          public class WindowsService {
      
              @Autowired
              private WindowsDao windowsDao;
      
              public Optional<List<Stuff>> getWindows(
                      final WindowCode windowCode) {
                  final Optional<List<Window>> windows = windowsDao.getWindows(
                          windowCode;
                  return windows;
              }
          }
      

      从此服务中调用:

          @Service
          @Transactional
          public class AssembleHouseService { 
              // some things
              @Autowired
              private WindowsService windowsService;
      
              public House buildHouse(final SomeParams params) {
                  // This service will fetch parts of the house
                  HouseBuilder builder = House.builder();
                  // call other services and then...
                  builder.windows(windowsService.getWindows(args).orElse(/*something*/));
                  //and then some more things...
              }
          }
      

      这是我用来配置数据源的原因:

          myDb:
          driver: db2
          schema: STUFF
          unique-resource-name: STUFF
          database-name: STUFF1
          server-name: myServer
          port: 12312
          username: hello
          password: world
          driver-type: 4
          min-pool-size: 2
          max-pool-size: 50
      

      的RowMapper:

      public class WindowsRowMapper implements RowMapper<Window> {
      
          @Override
          public Windows mapRow(final ResultSet rs, final int rowNum)
                  throws SQLException {
              return new BottomDealerText(
                      re.getString("WSIZE"),
                      rs.getString("DESCRIPTION"),
                      rs.getString("COLOR"));
          }
      }
      

2 个答案:

答案 0 :(得分:1)

如果您在同一个事务中有两个只读DAO,那么您可能遇到了Atomikos开源版本中的已知错误,该错误仅在此特定情况下显示。

它已在商业版中修复,但尚未在开源中修复。

希望有所帮助

答案 1 :(得分:0)

只需在这里发布寻找解决方法的人:

如果你不能改变为不同版本的atomikos(或者只是放弃它),对我有用的是添加

Propagation.REQUIRES_NEW

使用这些不同数据源的服务,因此它将是:

@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)

似乎将这两个读操作放入单独的事务中会使atomikos关闭事务并正确释放连接。

相关问题