我使用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的新会话。
如何以正确的方式使用预准备语句,以便不会创建新会话?
答案 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
方法。