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

时间:2018-03-26 16:24:16

标签: postgresql jdbc spring-jdbc apache-commons-dbcp

我使用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 -> {
        ...
    });

每次调用此选择查询时,都会创建一个到DB的新会话。

如果我省略预备语句并通过

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

一切正常:不会创建到DB的新会话。

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

1 个答案:

答案 0 :(得分:1)

您对jdbc.getDataSource().getConnection().createArrayOf的使用是获取新连接,并且因为您从未关闭所获得的连接而泄漏连接。

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

但是,您不需要创建该数组,JdbcTemplate明确支持使用IN的列表,请参阅Spring文档中的Passing in lists of values for IN clause。或者,请考虑使用Handling complex types for stored procedure calls中描述的SqlTypeValue方法。