我正在使用带有H2的内存数据库测试Dao。我正在将一个int传递给带有地图的查询以执行它。该查询在Oracle SQL上运行正常,但在H2中未成功。
道
@Override public int deleteCancelled(int days) { final Map<String, Object> namedParameters = new HashMap<String, Object>(); namedParameters.put(DAYS, days); namedParameters.put(STATUS, StatusEnum.CANCELLED.toString()); int updated = this.namedParameterJdbcTemplate.update(Query.QUERIES.DELETE_CANCELLED, namedParameters); return updated; }
查询
public static final String DELETE_CANCELLED = "DELETE FROM MY_TABLE " + "WHERE UPDATE_TS < SYSDATE - :days AND STATUS = :status";
当我尝试在H2上执行此查询时,它返回:
错误
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [DELETE FROM MY_TABLE WHERE UPDATE_TS < SYSDATE - ? AND STATUS = ?]; SQL state [HY004]; error code [50004]; Unknown data type : "?" Unknown data type: "?"; SQL statement: DELETE FROM MY_TABLE WHERE UPDATE_TS < SYSDATE - ? AND STATUS = ? [50004-196]; nested exception is org.h2.jdbc.JdbcSQLException: Unknown data type : "?" Unknown data type: "?"; SQL statement: DELETE FROM MY_TABLE WHERE UPDATE_TS < SYSDATE - ? AND STATUS = ? [50004-196]
我尝试执行对查询中的int进行硬编码的查询(SYSDATE = 4),并且可以正常工作,还尝试将原始int包装到Integer.valueOf(days)中,并使用MapSqlParameterSource指定哪种数据类型,但两者均无效。
为什么不起作用?有谁知道?提前致谢。
编辑:
状态枚举
public enum StatusEnum { CANCELLED("Cancelled"), CONFIRMED("Confirmed"), PENDING("Pending"), SENT("Sent"), private final String text; /** * @param text */ private StatusEnum(final String text) { this.text = text; } /* (non-Javadoc) * @see java.lang.Enum#toString() */ @Override public String toString() { return text; }
}
出现此异常似乎是因为H2试图在编译时对语句进行类型检查,并且无法唯一地确定参数的类型:它可以是日期,也可以是数字,或者其他。
解决方法(我提出的GitHub问题中提供)是替换
SYSDATE - ?
与
SYSDATE - CAST(? AS INTEGER)
我已经检查了它,它在H2和Oracle上均可使用。