SimpleJDBCTemplate和日期参数在某些情况下会产生奇怪的结果

时间:2014-04-24 12:18:40

标签: java spring oracle spring-jdbc

我为我的一个名为my_schema的oracle模式创建了一个函数,名为date2epoch:

create or replace function date2epoch(p_ora_date in date, p_offset in varchar2) return number is
  l_epoch_time number;
begin
  select floor((p_ora_date - to_date('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS')) * 86400 -
                                  to_number(substr(tz_offset(p_offset),1,3)) * 3600) ts into l_epoch_time from dual;
  return l_epoch_time;
end;

我还创建了一个名为date_to_et_epoch的函数:

create or replace function date_to_et_epoch(p_ora_date in date) return number is
begin
  return date2epoch(p_ora_date, 'Europe/Tallinn');
end;

如果我使用SQLPlus执行以下SQL-s,它们都可以工作:

select my_schema.date_to_et_epoch(trunc(to_date('22-JAN-2014'), 'MM')) from dual;
select 1 from dual where my_schema.date_to_et_epoch(SYSDATE) > my_schema.date_to_et_epoch(trunc(to_date('22-JAN-2014'), 'MM'));

现在我创建了一个J2EE应用程序,并希望在该应用程序中执行这些SQL。

首先是这个:

select my_schema.date_to_et_epoch(trunc(?, 'MM')) from dual

所以我基本上做的(这里有点简化版)是:

org.springframework.jdbc.core.namedparam.MapSqlParameterSource paramSource = new org.springframework.jdbc.core.namedparam.MapSqlParameterSource();
paramSource.addValue("mydate", new java.util.Date());
getSpringSimpleJDBCTemplate().query("select my_schema.date_to_et_epoch(trunc(:mydate, 'MM')) from dual", new MyRowMapper(), paramSource);

这很有效。

但如果我尝试第二个:

org.springframework.jdbc.core.namedparam.MapSqlParameterSource paramSource = new org.springframework.jdbc.core.namedparam.MapSqlParameterSource();
paramSource.addValue("mydate", new java.util.Date());
getSpringSimpleJDBCTemplate().query("select 1 from dual where my_schema.date_to_et_epoch(SYSDATE) > my_schema.date_to_et_epoch(trunc(:mydate, 'MM'))", new MyRowMapper(), paramSource);

我得到一个例外:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select 1 from dual where my_schema.date_to_et_epoch(SYSDATE) > my_schema.date_to_et_epoch(trunc(?, 'MM'))]; nested exception is java.sql.SQLException: ORA-06553: PLS-306: wrong number or types of arguments in call to 'DATE_TO_ET_EPOCH'.

我无法理解为什么会这样。我假设这样做可以解决Spring-s JDBC模板或Oracle驱动程序如何处理Java Date对象作为参数而不是SQL中的to_date。但是,是否有一些我在概念上做错了或者我能做些什么来解决这个问题?我宁愿在Java方面而不是SQL方面解决这个问题,因为SQL是由第三方组成的,并且可能会在一段时间内发生变化。

2 个答案:

答案 0 :(得分:2)

正如Pavel Horak在一个评论中建议的那样,在Java代码中明确地添加参数数据类型可以保存当天。

以各种方式工作的代码示例:

org.springframework.jdbc.core.namedparam.MapSqlParameterSource paramSource = new org.springframework.jdbc.core.namedparam.MapSqlParameterSource();
paramSource.addValue("mydate", new java.util.Date(), java.sql.Types.DATE);
getSpringSimpleJDBCTemplate().query("select 1 from dual where my_schema.date_to_et_epoch(SYSDATE) > my_schema.date_to_et_epoch(trunc(:mydate, 'MM'))", new MyRowMapper(), paramSource);

答案 1 :(得分:0)

如果查看导致异常的查询:

 org.springframework.jdbc.core.namedparam.MapSqlParameterSource paramSource = new org.springframework.jdbc.core.namedparam.MapSqlParameterSource();
 paramSource.addValue("myDate", new java.util.Date());     
 getSpringSimpleJDBCTemplate().query("select 1 from dual where my_schema.date_to_et_epoch(SYSDATE) > my_schema.date_to_et_epoch(trunc(:mydate, 'MM'))", new MyRowMapper(), paramSource);

参数地图绑定 myDate ,但在您的查询中,您有:mydate ...情况有差异