【发布时间】:2017-04-27 15:21:42
【问题描述】:
我在使用 Spring Boot 和 JdbcNamedTemplate 查询数据库时遇到连接池耗尽的问题。
它应该是这样工作的:
- 从外部获取请求,其中包含有关房屋应该如何建造的一些参数。
- 根据收到的参数,使用一些 REST 端点和两个 DAO 来收集数据。
- 使用数据创建 House 对象并将其返回。
- 收到更多请求...
目前的运作方式:
- 请求很好。
- 来自 REST 端点的数据 - 正常。带有 DAO 的数据 -> 仅适用于带有两个 DAO 的前 50 个请求,之后就不行了。当其中一个 DAO 被禁用时,不会阻止任何连接。
- 50栋房子建好后,休息要很久才能完工,最后没有窗户。
- 使其无法用于更多请求,因为它们只会超时。
当我调用端点超过 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
行映射器:
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"));
}
}
【问题讨论】:
-
不是一个答案,只是返回一个空列表来表示没有结果,而不是一个空的 Optional
- 。您的捕获 (EmptyResultDataAccessException) 是不必要的:如果查询没有返回结果,Spring 只会返回一个空列表。
-
感谢您的建议!
-
你的
WindowsRowMapper在做什么。我也很难相信禁用一个或另一个不会出现问题(我怀疑它仍然存在,但需要更长的时间,大约 100 个请求)。 -
我现在将进行更多测试并使用行映射器代码更新帖子。
-
您的代码/配置中一定有一些东西没有正确返回到池的连接。您正在使用
Atomikos,因此您正在使用 JTA,如果没有一个连接没有真正参与事务,请确保您的 JDBC 实际上支持 XA。
标签: java spring spring-boot dao jdbctemplate