Java Spring StoredProcess中的当前Sql日期导致ORA-01847:月日必须介于1和月的最后一天之间

Java Spring StoredProcess中的当前Sql日期导致ORA-01847:月日必须介于1和月的最后一天之间,java,sql,oracle,stored-procedures,Java,Sql,Oracle,Stored Procedures,我正在Java/Spring中编译当前系统日期,如下所示: Calendar calobj = Calendar.getInstance(); java.sql.Date currentSysDate = new java.sql.Date(calobj.getTime().getTime()); 检查此日期时,其格式如下: 2014-04-01 我正在将此值传递给扩展的storedProcess类的execute()方法,该方法位于Map(通过Oracle PL/SQL更新): 这导致在我

我正在Java/Spring中编译当前系统日期,如下所示:

Calendar calobj = Calendar.getInstance();
java.sql.Date currentSysDate = new java.sql.Date(calobj.getTime().getTime());
检查此日期时,其格式如下:

2014-04-01
我正在将此值传递给扩展的
storedProcess
类的
execute()
方法,该方法位于
Map
(通过Oracle PL/SQL更新):

这导致在我的单元测试期间引发以下异常:

ORA-01847: day of month must be between 1 and last day of month
ORA-06512: at line 4
; nested exception is java.sql.SQLDataException: ORA-01847: day of month must be between 1 and last day of month
ORA-06512: at line 4

你能完整地发布你的代码吗?您是否按照Alex Poole的要求使用正确的绑定类型?这个例子应该对您有用:

create or replace PROCEDURE update_curr_date(current_date  IN DATE)
is
begin
       insert into t values(current_date);
end;
/

class SP extends StoredProcedure{ 
        private static final String SPROC_NAME = "update_curr_date"; 
        public SP( DataSource datasource ){ 
               super( datasource, SPROC_NAME ); 
               declareParameter( new SqlParameter( "current_date", OracleTypes.DATE ) ); 
               compile(); 
        } 
        public Object execute(java.sql.Date p) { 
               Map<String,Object> results = super.execute(p); 
               return null;
        }
} 

...
    public void updateDate() {
        Calendar calobj = Calendar.getInstance();
        java.sql.Date currentSysDate = new java.sql.Date(calobj.getTime().getTime());        
        SP psp = new SP(jdbcTemplate.getDataSource());
        psp.execute(currentSysDate);
    }
...
创建或替换过程更新当前日期(日期中的当前日期)
是
开始
插入t值(当前日期);
结束;
/
类SP扩展了StoredProcedure{
私有静态最终字符串存储过程\u NAME=“更新当前日期”;
公共SP(数据源数据源){
超级(数据源、存储过程名称);
declareParameter(新的SqlParameter(“当前_日期”,OracleTypes.date));
编译();
} 
公共对象执行(java.sql.datep){
Map results=super.execute(p);
返回null;
}
} 
...
公共void updateDate(){
Calendar calobj=Calendar.getInstance();
java.sql.Date currentSysDate=new java.sql.Date(calobj.getTime().getTime());
SP psp=new SP(jdbcTemplate.getDataSource());
psp.execute(当前系统日期);
}
...

检查您的参数使用的日期类型绑定。

我使用的原始存储过程有多个必需的参数,包括
当前\u日期
。我收到了同样的异常,提示我减少所有参数,只使用
日期
参数无效

最后,我放弃并将所有参数放回PL/SQL存储过程中,并在
StoredProcedure
类中声明参数。问题是,我不明白为什么,参数的声明顺序,即:

PROCEDURE update_curr_date(
  h_id    IN NUMBER,
  h_type   IN VARCHAR2,
  h_pnum IN VARCHAR2,
  h_curr_date    IN DATE,
  mode         IN VARCHAR2 DEFAULT 'INSERT');
并在
存储过程中声明:

    declareParameter(new SqlParameter("h_id", OracleTypes.NUMBER));
    declareParameter(new SqlParameter("h_curr_date", OracleTypes.DATE));
    declareParameter(new SqlParameter("h_type", OracleTypes.VARCHAR));
    declareParameter(new SqlParameter("h_pnum", OracleTypes.VARCHAR));
和查询字符串:

{call update_curr_date (
h_id => :h_id,
h_type => :h_type,
h_curr_date => :h_curr_date,
h_pnum => :h_pnum
注意
模式
被动态地附加到SQL查询字符串的末尾及其相应的声明,因为它是一个可选参数,但这并不重要

当我将
h\u curr\u date
的声明移动到
declareParameter()
的末尾时,它起了作用:

    declareParameter(new SqlParameter("h_id", OracleTypes.NUMBER));
    declareParameter(new SqlParameter("h_type", OracleTypes.VARCHAR));
    declareParameter(new SqlParameter("h_pnum", OracleTypes.VARCHAR));
    declareParameter(new SqlParameter("h_curr_date", OracleTypes.DATE));

考虑到我正在使用一个命名参数来进行声明和绑定变量,奇怪的是,在这种情况下,当参数声明顺序不正确时,Spring(或者JDBC的Oracle实现,但我怀疑前者是在Spring代码中完成映射的)不起作用(我也在
OUT
参数方面遇到了一些奇怪的结果)。

@HamletHakobyan添加了Spring和PL/SQL接口中使用的查询字符串。我认为这些附加信息并不相关,因为在SQL Developer中运行时,包装器在传递相同的确切日期格式('2014-04-01')时执行得很好@Malvon-这是相关的,因为您的过程期望参数是日期正在传递一个字符串,因此两个会话都在隐式转换为
date
;由于一个有效,另一个无效,这两个会话具有不同的
NLS\u date\u格式设置。您有一个
sql.date
,但它在绑定时似乎被转换为字符串;不过您还没有显示绑定步骤。@AlexPoole你能详细说明一下绑定步骤吗?我不太明白。谢谢。@Malvon-你正在用绑定变量
:current_date
执行
调用
;你能包括将值(bind)设置为
参数
current_date
的代码吗?我假设这是
setString()
调用。(除非Spring在幕后为您处理;我不使用另一种技术!)@AlexPoole我明白了。该值直接传递给
execute()
,Spring的
StoredProcedure
类负责处理细节(
CallableStatement
)内部。我的代码与您的代码相同,具有正确的绑定类型
OracleTypes.DATE
。即使我传递了
null
,我也会得到相同的错误。为什么?甚至
new java.sql.Timestamp(System.currentTimeMillis())
也会重复相同的异常。
{call update_curr_date (
h_id => :h_id,
h_type => :h_type,
h_curr_date => :h_curr_date,
h_pnum => :h_pnum
    declareParameter(new SqlParameter("h_id", OracleTypes.NUMBER));
    declareParameter(new SqlParameter("h_type", OracleTypes.VARCHAR));
    declareParameter(new SqlParameter("h_pnum", OracleTypes.VARCHAR));
    declareParameter(new SqlParameter("h_curr_date", OracleTypes.DATE));