Apache DBCP 2:如果使用带有数组的准备语句,则创建新会话



我使用 Spring Boot、Apache DBCP 2、PostgreSQL 10 并通过

@Bean
public JdbcTemplate getJdbcTemplate() {
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
Properties props = new Properties();
props.setProperty(PGProperty.USER.getName(), user);
props.setProperty(PGProperty.PASSWORD.getName(), password);
props.setProperty(PGProperty.APPLICATION_NAME.getName(), applicationName);
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:postgresql://" + host + "/db",
props);
PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory);
poolableConnectionFactory.setPool(connectionPool);
PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
return new JdbcTemplate(dataSource);
}

我通过以下方式访问数据库

@Autowired
private JdbcTemplate jdbc;
...
UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.randomUUID();
Array array = jdbc.getDataSource().getConnection().createArrayOf("UUID", 
new Object[] { uuid1, uuid2 });
jdbc.query("SELECT * FROM my_table WHERE id = ANY (?)", //
ps -> ps.setArray(1, array), //
rs -> {
...
});

每次调用此选择查询时,都会创建与数据库的新会话。

如果我省略了准备好的语句并通过以下方式调用数据库

jdbc.query("SELECT * FROM my_table "
+ "WHERE id IN ('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb')",
rs -> {
...
});

一切正常:不会创建到数据库的新会话。

如何以正确的方式使用预准备语句,而不会创建新会话?

您对jdbc.getDataSource().getConnection().createArrayOf的用法是获取新连接,并且由于您从未关闭该获得的连接而泄漏连接。

如果要获取JdbcTemplate使用的连接,则需要使用DataSourceUtils.getConnection

但是,您不需要创建该数组,JdbcTemplate明确支持使用IN列表,请参阅 Spring 文档中的传入 IN 子句的值列表。或者,考虑使用处理存储过程调用的复杂类型中所述SqlTypeValue的方法。

相关内容

  • 没有找到相关文章

最新更新