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

Java 使用命名的JDBC参数调用存储过程会引发异常,java,sql-server,jdbc,Java,Sql Server,Jdbc,因此,当我试图运行我的线束,连接。但是,当程序试图调用我的存储过程“iCurrentLocations01”时。它在我的日志中返回错误消息 “2016-01-27 13:11:17错误SQLConnection:97-参数运行日期为 未为存储过程iCurrentLocations01定义。“ 有人能解释一下我做错了什么吗?程序btw从LDAP目录获取信息并将其插入本地数据库 编辑-这是我的存储过程: package com.brookfieldres.operations; import ja

因此,当我试图运行我的线束,连接。但是,当程序试图调用我的存储过程“iCurrentLocations01”时。它在我的日志中返回错误消息

“2016-01-27 13:11:17错误SQLConnection:97-参数运行日期为 未为存储过程iCurrentLocations01定义。“

有人能解释一下我做错了什么吗?程序btw从LDAP目录获取信息并将其插入本地数据库

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

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;
            }

使用基于索引的集合方法

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

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

  • 在命令文本中按任意顺序指定参数,然后
  • 忽略具有默认值的参数
对于存储过程

创建过程[dbo]。[my_sp]
@p1 nvarchar(10)=你好,
@p2 nvarchar(10)=N'world'
作为
开始
不计数;
选择@p1+N'、“+@p2+N”!”作为回应;
结束
JDBC调用

try(CallableStatement s=conn.prepareCall(“{CALL my_sp(@p2=?)}”)){
s、 设置管柱(1,“Gord”);
try(ResultSet rs=s.executeQuery()){
rs.next();
System.out.println(rs.getString(“response”);
}
}
返回

你好,戈德!
(使用Microsoft JDBC Driver 4.1 for SQL Server进行了测试。)

认为消息是明确的好答案在评论中!但是,我不想使用它,因为将来如果我更改列的顺序。如果您想使用命名参数,则不应使用
是位置参数,只能通过索引进行设置。您可能需要检查驱动程序是否支持命名参数;在这种情况下,您可能需要使用SQL Server特定的语法,而不是
调用
转义(但我不确定)。
           _cs = getConnection().prepareCall("{call iCurrentLocations01(?, ?, ?, ?)}");
            _cs.setTimestamp(1, RunDate);
            _cs.setString(2, rlpCompanyid);
            _cs.setString(3, rlpLocationid);
            _cs.setString(4, rlpOpenDate );
            returnVal = _cs.executeUpdate(); 
            System.out.println("2");