【发布时间】:2014-09-28 22:41:10
【问题描述】:
我继承了一个具有以下设置的项目:
- spring 框架:3.2.2
- oracle 驱动程序:ojdbc6.jar:11.2.0.4
- c3p0 用于连接池:0.9.1.2
- 它利用动态数据源路由,我认为这篇文章的灵感来自http://spring.io/blog/2007/01/23/dynamic-datasource-routing/
声明的类和用于执行查询的方法之一如下所示
public class DataSourceServiceImpl extends SimpleJdbcDaoSupport implements DataSourceService {
...
public List<Map<String, Object>> valueList(String dataSource, Object[] params, String sql) throws DataAccessException {
DataSourceContextHolder.setDataSource(dataSource);
return getSimpleJdbcTemplate().getJdbcOperations().queryForList(sql, params);
}
}
示例 SQL:
SELECT samplefield FROM sampletable WHERE SDE.ST_INTERSECTS(SHAPE, SDE.ST_GEOMETRY(?, ?)) = 1 AND SHAPE IS NOT NULL
问题是,如果输入字符串(表示几何)超过 Oracle 驱动程序的 4000 个字符限制,我们会得到 p>
ORA-01460:请求的转换未实现或不合理
换句话说,这意味着 queryForList(以及它后面的任何东西)不会自动处理超出限制的字符串。
经过一番研究,我意识到我必须使用 c3p0 OracleUtils 来生成临时 Clob。所以我修改了代码以检查参数并相应地修改它们:
try {
Connection conn = getConnection();
for (Object obj: params){
if (obj instanceof String && obj.toString().length() > 4000){
Clob clob = OracleUtils.createTemporaryCLOB(conn, true, 10);
clob.setString(1, (String)obj);
clobs.add(clob);
params[i] = clob; // re-assign the parameter back
}
i++;
}
List<Map<String, Object>> result = getSimpleJdbcTemplate().getJdbcOperations().queryForList(sql, params);
if (!clobs.isEmpty())
for (Clob c: clobs) c.free();
} catch (SQLException e) {
e.printStackTrace();
}
很遗憾,这导致了另一个 Oracle 错误:
ORA-22922:LOB 值不存在
经过另一项研究,我意识到我分配给“params”参数的临时 Clob 的指针是空的,很可能是由于“queryForList”在不同的连接中执行 (!),而不是用于生成临时 Clob 的那个。所以我最终得到了以下结果:
JdbcTemplate t = new JdbcTemplate(new SingleConnectionDataSource(conn, false));
result = t.queryForList(sql, params);
这行得通,但恐怕这不是最佳选择,只会在将来的某个时候引起问题。
我的问题是,有没有办法重用用于为实际查询生成 CLOB 的连接?
【问题讨论】:
标签: java spring oracle c3p0 clob