如何使用 jdbctemplate 从 Java 执行匿名 PL/SQL
How to execute anonymous PL/SQL from Java using jdbctemplate
我想从 Java
调用此查询(当 运行 对 SQL 开发人员时有效)
DECLARE
TYPE my_id_tab IS
TABLE OF my_table.my_id%TYPE;
my_ids my_id_tab;
BEGIN
UPDATE my_table
SET
another_id = NULL
WHERE
another_id IS NULL
AND create_datetime BETWEEN '03-JUN-19' AND '05-JUN-19'
RETURNING my_id BULK COLLECT INTO my_ids;
COMMIT;
END;
但我相信 Java 很难弄清楚我想要 my_ids 的 collection 返回给我。
这是我到目前为止尝试的异常消息,如 java.sql.SQLException: Invalid column index
或者
java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!
final Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
try (final CallableStatement callableStatement = connection.prepareCall(TEST_SQL))
{
callableStatement.registerOutParameter("my_ids", Types.ARRAY);
callableStatement.executeUpdate();
int[] arr = (int[]) callableStatement.getArray("my_ids").getArray();
return Arrays.stream(arr).boxed().collect(Collectors.toSet());
}
catch (final SQLException e)
{
LOG.info("threw exception, {}", e);
}
finally
{
DataSourceUtils.releaseConnection(connection, jdbcTemplate.getDataSource());
}
这不是最简单的事情,但很容易做到。您将需要在 Oracle 中创建一个 TYPE 来定义结果。
对于此演示,创建并填充 EMP 和 DEPT:EMP and DEPT script
创建 TYPE
,需要定义将返回的数组:
create type t_integer_array as table of integer;
我们将运行以下UPDATE
,它只会更新几行:
UPDATE emp
SET job = job -- a nonsense update
WHERE comm IS NOT NULL -- only affect some of the rows
这里是 Java:
package test;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;
import java.util.Arrays;
public class OracleTest {
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"<your JDBC url>", "<your user>", "<your password>");
// Prepare the call, without defining the the output variable
// in a DECLARE section of the PL/SQL itself, you just need to
// include a "?" and then associate the correct type in the
// next step.
CallableStatement cs = conn.prepareCall(
"BEGIN\n"
+ " UPDATE emp\n"
+ " SET job = job\n"
+ " WHERE comm is not null\n"
+ " RETURNING empno BULK COLLECT INTO ?;\n"
+ "END;");
// Register the single OUT parameter as an array, using the
// type that was defined in the database, T_INTEGER_ARRAY.
cs.registerOutParameter(1, Types.ARRAY, "T_INTEGER_ARRAY");
cs.execute();
// Now get the array back, as array of BigDecimal.
// BigDecimal is used because it doesn't have precision
// problems like floating point, it will contain all digits
// that the database provided.
BigDecimal[] nums = (BigDecimal[]) (cs.getArray(1).getArray());
System.out.println(Arrays.toString(nums));
cs.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
这是我的输出:
[7499, 7521, 7654, 7844]
这些是仅适用于受更新影响的行的技术密钥 (empno
)。
我想从 Java
调用此查询(当 运行 对 SQL 开发人员时有效)DECLARE
TYPE my_id_tab IS
TABLE OF my_table.my_id%TYPE;
my_ids my_id_tab;
BEGIN
UPDATE my_table
SET
another_id = NULL
WHERE
another_id IS NULL
AND create_datetime BETWEEN '03-JUN-19' AND '05-JUN-19'
RETURNING my_id BULK COLLECT INTO my_ids;
COMMIT;
END;
但我相信 Java 很难弄清楚我想要 my_ids 的 collection 返回给我。
这是我到目前为止尝试的异常消息,如 java.sql.SQLException: Invalid column index
或者
java.sql.SQLException: operation not allowed: Ordinal binding and Named binding cannot be combined!
final Connection connection = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
try (final CallableStatement callableStatement = connection.prepareCall(TEST_SQL))
{
callableStatement.registerOutParameter("my_ids", Types.ARRAY);
callableStatement.executeUpdate();
int[] arr = (int[]) callableStatement.getArray("my_ids").getArray();
return Arrays.stream(arr).boxed().collect(Collectors.toSet());
}
catch (final SQLException e)
{
LOG.info("threw exception, {}", e);
}
finally
{
DataSourceUtils.releaseConnection(connection, jdbcTemplate.getDataSource());
}
这不是最简单的事情,但很容易做到。您将需要在 Oracle 中创建一个 TYPE 来定义结果。
对于此演示,创建并填充 EMP 和 DEPT:EMP and DEPT script
创建 TYPE
,需要定义将返回的数组:
create type t_integer_array as table of integer;
我们将运行以下UPDATE
,它只会更新几行:
UPDATE emp
SET job = job -- a nonsense update
WHERE comm IS NOT NULL -- only affect some of the rows
这里是 Java:
package test;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;
import java.util.Arrays;
public class OracleTest {
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"<your JDBC url>", "<your user>", "<your password>");
// Prepare the call, without defining the the output variable
// in a DECLARE section of the PL/SQL itself, you just need to
// include a "?" and then associate the correct type in the
// next step.
CallableStatement cs = conn.prepareCall(
"BEGIN\n"
+ " UPDATE emp\n"
+ " SET job = job\n"
+ " WHERE comm is not null\n"
+ " RETURNING empno BULK COLLECT INTO ?;\n"
+ "END;");
// Register the single OUT parameter as an array, using the
// type that was defined in the database, T_INTEGER_ARRAY.
cs.registerOutParameter(1, Types.ARRAY, "T_INTEGER_ARRAY");
cs.execute();
// Now get the array back, as array of BigDecimal.
// BigDecimal is used because it doesn't have precision
// problems like floating point, it will contain all digits
// that the database provided.
BigDecimal[] nums = (BigDecimal[]) (cs.getArray(1).getArray());
System.out.println(Arrays.toString(nums));
cs.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
这是我的输出:
[7499, 7521, 7654, 7844]
这些是仅适用于受更新影响的行的技术密钥 (empno
)。