java - 使用命名 JDBC 参数调用存储过程会引发异常

标签 java sql-server jdbc

package com.brookfieldres.operations;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Properties;
import java.util.ResourceBundle;

import org.apache.log4j.Logger;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;

public class SQLConnection {

private static Connection acon = null; 
private static CallableStatement _cs = null; 
private static String _dbServer = null; 
private static String _dbUsername =  null; 
private static String _dbPassword = null;
    private static String _dbName = null;
private static String _dbInstance = null;
private static String _dbWindowsAuthentication = null;


    private static final Logger aLogger = Logger.getLogger(SQLConnection.class.getName());
//  static ResourceBundle resource = ResourceBundle.getBundle("Resource");






 public SQLConnection() {
        _dbServer = "localhost"; 
        _dbUsername = "NewLocationTestUser";
        _dbPassword = "TestPass123";
        _dbName = "NewLocationDB";
        _dbInstance = "APPSQL";
        _dbWindowsAuthentication = "FALSE";
    }

 public Connection getConnection() {

        SQLServerDataSource ds = new SQLServerDataSource();
        Properties properties = new Properties();

        try {
            String dbURL = "jdbc:sqlserver://" + _dbServer;
            if(!_dbInstance.equalsIgnoreCase(""))
            {
                dbURL += "\\" + _dbInstance;
            }
            if(_dbWindowsAuthentication.equalsIgnoreCase("TRUE"))
            {
                dbURL += ";integratedSecurity=true";
            }
            else
            {
                properties.put("user", _dbUsername);
                properties.put("password", _dbPassword);
            }
            dbURL += ";";
            properties.put("database", _dbName);
            acon = DriverManager.getConnection(dbURL, properties);
            System.out.println("1");


         } catch (Exception e) {
             aLogger.error(e.getMessage());
         }
         finally {
            ds = null;
         }
        aLogger.info("The sql connection has been established.");
        return acon;
 }

 public int insertLocations(Timestamp RunDate, String rlpCompanyid, String rlpLocationid,  String rlpOpenDate){

     int returnVal = 0; 

            try{ 

                _cs = getConnection().prepareCall("{call iCurrentLocations01(?, ?, ?, ?)}");
                _cs.setTimestamp("RunDate", RunDate);
                _cs.setString("CompanyId", rlpCompanyid);
                _cs.setString("LocationId", rlpLocationid);
                _cs.setString("rlpOpenDate", rlpOpenDate );
                returnVal = _cs.executeUpdate(); 
                System.out.println("2");

            }catch (SQLException e){
                aLogger.error(e.getMessage());
                }finally {
                    if (_cs != null){ 
                        try{ 
                            _cs.close();
                        }catch(SQLException e) { 
                            aLogger.error(e.getMessage());
                        }
                    }
                 }
            return returnVal;
            }

所以当我尝试运行我的安全带时,连接就建立了。但是,当程序尝试调用我的存储过程“iCurrentLocations01”时。它在我的日志中返回错误消息

" 2016-01-27 13:11:17 ERROR SQLConnection:97 - Parameter RunDate was not defined for stored procedure iCurrentLocations01."

有人可以解释一下我在这里做错了什么吗?顺便说一句,该程序正在从 LDAP 目录获取信息并将其插入本地数据库。

编辑 - 这是我的存储过程:

USE [NewLocationDB]
GO

/****** Object:  StoredProcedure [dbo].[iCurrentLocations01]    Script Date:     01/27/2016 1:27:10 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO




ALTER PROCEDURE [dbo].[iCurrentLocations01]
@RunDate datetime, 
@CompanyId varchar, 
@LocationId varchar, 
@rlpOpenDate varchar 

AS 
DECLARE @RetVal int 
SET @RetVal = 0 

INSERT CurrentLocations (RunDate, CompanyId, LocationId, rlpOpenDate )
VALUES (@RunDate, @CompanyId, @LocationId, @rlpOpenDate)

SET @RetVal = @@ERROR
Return @RetVal

GO

最佳答案

这可能并不完全是您所希望的,但它确实可以按名称将参数传递给存储过程,从而使我们能够

  • 在命令文本中以任意顺序指定参数,并且
  • 省略具有默认值的参数。

对于存储过程

CREATE PROCEDURE [dbo].[my_sp] 
    @p1 nvarchar(10) = N'Hello', 
    @p2 nvarchar(10) = N'world'
AS
BEGIN
    SET NOCOUNT ON;
    SELECT @p1 + N', ' + @p2 + N'!' AS response;
END

JDBC 调用

try (CallableStatement s = conn.prepareCall("{CALL my_sp (@p2=?)}")) {
    s.setString(1, "Gord");
    try (ResultSet rs = s.executeQuery()) {
        rs.next();
        System.out.println(rs.getString("response"));
    }
}

返回

Hello, Gord!

(使用 Microsoft JDBC Driver 4.1 for SQL Server 进行测试。)

关于java - 使用命名 JDBC 参数调用存储过程会引发异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61264151/

相关文章:

sql-server - 如何使用 SSIS 将多个 Access 数据库导入 SQL Server

java - Java程序中的Multiple Delete MSSQL删除查询

java - 您如何正确关闭 JDBC 连接以供重用?

java - Hibernate 不使用 spring boot 从 mysql 表返回数据

java - 以原子方式移动和重命名 Path 实例

c# - 解析和插入批量数据。如何保持业绩和做关系?

java - 安装 Snowflake JDBC 驱动程序

java - 如何在两个jsp之间发送数据?

java - 从字符串中提取子字符串

c# - 调用存储过程或运行sql查询?