在 Spring Boot 和 Oracle 中使用 STRUCTS 时未释放连接
Connections not being released when using STRUCTS in Spring Boot and Oracle
我有一个 Spring 引导应用程序,我在其中托管多个 REST 和 SOAP Web 服务。我客户的最新请求是执行一个存储过程,该过程接收多个参数和 3 个自定义数组。
似乎工作正常,但在执行 5 次后,出现以下错误:
Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:5; busy:5; idle:0; lastwait:30000].
我不明白为什么在使用此特定功能时连接没有被释放。
我从 Spring 扩展 StoredProcedure
:
public class OracleArrayStoredProcedure extends StoredProcedure {
在那之后,我的参数有一堆最终字符串(超过 50 个),然后我有构造函数:
public OracleArrayStoredProcedure(DataSource ds) {
super(ds, PROC_NAME);
在构造函数中我有参数,其中还包括数组:
declareParameter(new SqlParameter(PARAM1, OracleTypes.NUMBER));
// Arrays
declareParameter(new SqlInOutParameter(ARRAY1, OracleTypes.ARRAY, "ARRAY1"));
declareParameter(new SqlInOutParameter(ARRAY2, OracleTypes.ARRAY, "ARRAY2"));
declareParameter(new SqlInOutParameter(ARRAY3, OracleTypes.ARRAY, "ARRAY3"));
compile();
然后我有执行,这是我获得无法释放的连接的地方:
public ArrayResponse execute(ArrayRequest arrayRequest) {
ArrayResponse response = new ArrayResponse();
Map<String, Object> inputs = new HashMap<String, Object>();
try {
OracleConnection connection = getJdbcTemplate().getDataSource().getConnection()
.unwrap(OracleConnection.class);
// ARRAY1
ArrayDescriptor arrayFirstDescriptor = new ArrayDescriptor(ARRAY1, connection);
StructDescriptor recFirstDescriptor = new StructDescriptor("FIRSTREC", connection);
Object[] arrayFirstStruct = new Object[arrayRequest.getArray1().size()];
int i = 0;
for (Iterator<Array1> iterator = arrayRequest.getArray1().iterator(); iterator
.hasNext();) {
Model1 model1 = (Model1) iterator.next();
STRUCT s = new STRUCT(arrayFirstDescriptor, connection, new Object[] {
// Bunch of attributes
arrayStructArray[i++] = s;
}
ARRAY inStructArray = new ARRAY(arrayDescriptor, connection, array1Struct);
最后我将数组和参数放入输入映射并执行它:
inputs.put(ARRAY1, inStructArray);
Map<String, Object> out = super.execute(inputs);
这种方法的问题是我无法释放连接(即使我使用 connection.close()),所以在执行 5 次后它不再起作用。我做错了什么?
当我不必使用 STRUCT 时,我不需要使用
OracleConnection connection = getJdbcTemplate().getDataSource().getConnection()
.unwrap(OracleConnection.class);
所以一切正常。
我能够通过实现 AbstractSqlTypeValue() 来修复它,它有一个传递数据源连接的方法。这样,我就不必手动建立连接。然后我只需将 structArray 添加到输入映射。
SqlTypeValue structArray = new AbstractSqlTypeValue() {
@Override
protected Object createTypeValue(Connection connection, int arg1, String arg2) throws SQLException {
Object[] modelArray = new Object[request.getArray().size()];
int i = 0;
for (Iterator<Model> iterator = request.getArray().iterator(); iterator.hasNext();) {
Model model = (Model) iterator.next();
Struct s = connection.createStruct("TEST_REC", new Object[] {
// All attributes go here
});
modelArray[i++] = s;
}
Array structArray = ((OracleConnection) connection).createOracleArray("TEST_STRUCT",
modelArray);
return structArray ;
}
};
我有一个 Spring 引导应用程序,我在其中托管多个 REST 和 SOAP Web 服务。我客户的最新请求是执行一个存储过程,该过程接收多个参数和 3 个自定义数组。
似乎工作正常,但在执行 5 次后,出现以下错误:
Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[size:5; busy:5; idle:0; lastwait:30000].
我不明白为什么在使用此特定功能时连接没有被释放。
我从 Spring 扩展 StoredProcedure
:
public class OracleArrayStoredProcedure extends StoredProcedure {
在那之后,我的参数有一堆最终字符串(超过 50 个),然后我有构造函数:
public OracleArrayStoredProcedure(DataSource ds) {
super(ds, PROC_NAME);
在构造函数中我有参数,其中还包括数组:
declareParameter(new SqlParameter(PARAM1, OracleTypes.NUMBER));
// Arrays
declareParameter(new SqlInOutParameter(ARRAY1, OracleTypes.ARRAY, "ARRAY1"));
declareParameter(new SqlInOutParameter(ARRAY2, OracleTypes.ARRAY, "ARRAY2"));
declareParameter(new SqlInOutParameter(ARRAY3, OracleTypes.ARRAY, "ARRAY3"));
compile();
然后我有执行,这是我获得无法释放的连接的地方:
public ArrayResponse execute(ArrayRequest arrayRequest) {
ArrayResponse response = new ArrayResponse();
Map<String, Object> inputs = new HashMap<String, Object>();
try {
OracleConnection connection = getJdbcTemplate().getDataSource().getConnection()
.unwrap(OracleConnection.class);
// ARRAY1
ArrayDescriptor arrayFirstDescriptor = new ArrayDescriptor(ARRAY1, connection);
StructDescriptor recFirstDescriptor = new StructDescriptor("FIRSTREC", connection);
Object[] arrayFirstStruct = new Object[arrayRequest.getArray1().size()];
int i = 0;
for (Iterator<Array1> iterator = arrayRequest.getArray1().iterator(); iterator
.hasNext();) {
Model1 model1 = (Model1) iterator.next();
STRUCT s = new STRUCT(arrayFirstDescriptor, connection, new Object[] {
// Bunch of attributes
arrayStructArray[i++] = s;
}
ARRAY inStructArray = new ARRAY(arrayDescriptor, connection, array1Struct);
最后我将数组和参数放入输入映射并执行它:
inputs.put(ARRAY1, inStructArray);
Map<String, Object> out = super.execute(inputs);
这种方法的问题是我无法释放连接(即使我使用 connection.close()),所以在执行 5 次后它不再起作用。我做错了什么?
当我不必使用 STRUCT 时,我不需要使用
OracleConnection connection = getJdbcTemplate().getDataSource().getConnection()
.unwrap(OracleConnection.class);
所以一切正常。
我能够通过实现 AbstractSqlTypeValue() 来修复它,它有一个传递数据源连接的方法。这样,我就不必手动建立连接。然后我只需将 structArray 添加到输入映射。
SqlTypeValue structArray = new AbstractSqlTypeValue() {
@Override
protected Object createTypeValue(Connection connection, int arg1, String arg2) throws SQLException {
Object[] modelArray = new Object[request.getArray().size()];
int i = 0;
for (Iterator<Model> iterator = request.getArray().iterator(); iterator.hasNext();) {
Model model = (Model) iterator.next();
Struct s = connection.createStruct("TEST_REC", new Object[] {
// All attributes go here
});
modelArray[i++] = s;
}
Array structArray = ((OracleConnection) connection).createOracleArray("TEST_STRUCT",
modelArray);
return structArray ;
}
};