从 java.sql.CallableStatement 调用的存储过程中检索记录

Retrieve a record from a stored procedure, invoked from java.sql.CallableStatement

我正在创建一个网络应用程序,用户可以在其中为某些网络文档设置警报。这个日期与一堆其他数据一起存储在 mysql 数据库中,这些数据在插入时使用 AES_ENCRYPT 加密。

插入的过程如下所示:

CREATE DEFINER=`service01`@`%` PROCEDURE `insert_secure_alert`(
IN master_secret VARCHAR(100), 
IN path VARCHAR(300),
IN creation DATE,
IN expiration DATE,
IN alert_name VARCHAR(300),
IN alert_comment VARCHAR(300)
)
BEGIN
INSERT INTO `fujitsu_consensus_core`.`alert`
(`id`,
`path`,
`creation`,
`expiration`,
`name`,
`comment`)
VALUES
(0,
AES_ENCRYPT(path, master_secret),
AES_ENCRYPT(creation, master_secret),
AES_ENCRYPT(expiration, master_secret),
AES_ENCRYPT(alert_name, master_secret),
AES_ENCRYPT(alert_comment, master_secret));
END

一切正常,但是我在使用存储过程检索此数据时遇到了一些问题。负责此检索的 class 如下所示:

package com.fujitsu.database;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;

import com.fujitsu.consensus.helper.StreamToJson;

public class RetrieveSecureAlert extends HttpServlet{

/**
 * 
 */
private static final long serialVersionUID = -6379032803226212817L;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException{

    try {
        JSONObject obj = StreamToJson.convertStreamToJson(req.getInputStream());
        String path = (String) obj.get("path");

        CallableStatement cs = AccessObject.getConnectionObject().prepareCall("{CALL `fujitsu_consensus_core`.`retrieve_secure_alert`(?,?}");
        cs.setString(1, path);
        cs.setString(2, "FUJITSU");
        cs.execute();

        ResultSet result = cs.getResultSet();

        System.out.println("RESULT!");
        while(result.next()){
            System.out.println(result.getString("id"));
            System.out.println(result.getString("decryptd_path"));
            System.out.println(result.getString("decrypted_creation"));
            System.out.println(result.getString("decrypted_expiration"));
            System.out.println(result.getString("decrypted_name"));
            System.out.println(result.getString("decrypted_comment"));
        }


    } catch (ParseException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

对应的mysql存储过程如下所示:

CREATE DEFINER=`service01`@`%` PROCEDURE `retrieve_secure_alert`(IN path_key VARCHAR(300), IN master_secret VARCHAR(100))
BEGIN

DECLARE v_encrypted_path VARBINARY(300);
DECLARE v_encrypted_creation VARBINARY;
DECLARE v_encrypted_expiration VARBINARY;
DECLARE v_encrypted_name VARBINARY(300);
DECLARE v_encrypted_comment VARBINARY(300);

SELECT path INTO v_encrypted_path FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT creation INTO v_encrypted_creation FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT expiration INTO v_encrypted_expiration FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);
SELECT `name` INTO v_encrypted_name FROM fujitsu_consensus_core WHERE path = path = AES_ENCRYPT(path_key, master_secret);
SELECT `comment` INTO v_encrypted_comment FROM fujitsu_consensus_core WHERE path = AES_ENCRYPT(path_key, master_secret);

SELECT  id,
    AES_DECRYPT(v_encrypted_path, master_secret) AS decryptd_path,
    AES_DECRYPT(v_encrypted_creation, master_secret) AS decrypted_creation,
    AES_DECRYPT(v_encrypted_expiration, master_secret) AS decrypted_expiration,
    AES_DECRYPT(v_encrypted_name, master_secret) AS decrypted_name,
    AES_DECRYPT(v_encrypted_comment, master_secret) AS decrypted_comment
FROM fujitsu_consensus_core.alert
WHERE path = AES_ENCRYPT(path_key, master_secret);
END

堆栈跟踪:

java.sql.SQLException: Unable to retrieve metadata for procedure.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
at com.mysql.jdbc.CallableStatement.extractProcedureName(CallableStatement.java:659)
at com.mysql.jdbc.CallableStatement.determineParameterTypes(CallableStatement.java:498)
at com.mysql.jdbc.CallableStatement.<init>(CallableStatement.java:403)
at com.mysql.jdbc.Connection.parseCallableStatement(Connection.java:4161)
at com.mysql.jdbc.Connection.prepareCall(Connection.java:4235)
at com.mysql.jdbc.Connection.prepareCall(Connection.java:4209)
at com.fujitsu.database.RetrieveSecureAlert.doPost(RetrieveSecureAlert.java:29)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

所以最大的问题是,如何使用解密我的记录的 java.sql.callablestatement 从 mysql 中的存储过程检索记录?

但是我发现了错误,callablestatement 中的 sql 字符串不能包含 ` 但应该包含 '