从始终加密的 SQL Server 数据库调用任何存储过程时,出现以下错误:
SQLServerException:传入的表格数据流(TDS)远程过程调用(RPC)协议流不正确。参数 1 (""):数据类型 0xC0 未知。
表和存储过程是这样创建的:
CREATE TABLE [dbo].[test_table] (
[id] [int] IDENTITY(1,1) NOT NULL,
[encrypted_col] [nvarchar](255) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [MY_KEY], ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NOT NULL
)
GO
CREATE PROCEDURE [dbo].[test_sp]
@test_param nvarchar(255)
AS
SELECT * from test_table where encrypted_col = @test_param
GO
java代码如下所示:
try(CallableStatement callableStatement = connection.prepareCall("{call test_sp(?)}")) {
callableStatement.setNString(1, "TEST VALUE");
ResultSet rs = callableStatement.executeQuery(); <-- Throws the Exception
}
我的连接网址如下所示:
jdbc:sqlserver://localhost:1433;applicationName=MY-APP;databaseName=test_encryption;sendStringParametersAsUnicode=false;encrypt=true;trustServerCertificate=true;columnEncryptionSetting=enabled;enclaveAttestationUrl=http://localhost/Attestation;enclaveAttestationProtocol=HGS;
导致此错误的原因是什么?
备注:
解决方法
我找到了一种解决方法,即使用PreparedStatement 并在sql 查询字符串中手动声明参数类型。示例:
String sql = "declare @test_param nvarchar(255) = ?;" +
"exec test_sp @p1";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setNString(1, "test");
ResultSet rs = statement.executeQuery();
如果没有在 SQL 字符串中手动声明参数类型,数据库似乎无法将参数类型与包含正在搜索的值的列的类型进行匹配。