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

Apache DBCP 2: new session created if prepared statement with array is used

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

生成 JdbcTemplate
@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 -> {
        ...
    });

每次调用此 select 查询时,都会创建一个新的数据库会话。

如果我省略准备好的语句并通过

调用数据库
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 使用列表,请参阅 Passing in lists of values for IN clause in the Spring documentation. Or alternatively, consider the approach using SqlTypeValue described in Handling complex types for stored procedure calls