在 H2 [SPRING-BOOT] 上通过 NamedParameterJDBCTemplate 使用整数时未知数据类型
Unknown data type when using an integer over NamedParameterJDBCTemplate on H2 [SPRING-BOOT]
我正在使用带 H2 的内存数据库测试 Dao。我将一个 int 传递给带有地图的查询以执行它。此查询在 Oracle SQL 上运行正常,但在 H2 中未成功。
DAO
@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 上执行此查询时,它 returns:
错误
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 指定哪种数据类型是, 但 none 两者都有效。
为什么不起作用?有谁知道?提前致谢。
编辑:
StatusEnum
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 issue I raised中提供)是替换
SYSDATE - ?
和
SYSDATE - CAST(? AS INTEGER)
我已经检查过了,它适用于 H2 和 Oracle。
对于整数参数(Spring 数据)有解决方法:包含参数并添加 0
:
@Query(value = "DELETE FROM my_table WHERE update_ts < SYSDATE - (:days + 0)")
void cleanup(@Param("days") Integer days);
我正在使用 namedQuery,这对我有用。如果它可以帮助别人。
CAST(:variable AS double)
为了尊重休眠类型,它必须是小写的:
https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#mapping-types-basictypes
@Luke 的解决方案有效,但我不得不改为小写
我正在使用带 H2 的内存数据库测试 Dao。我将一个 int 传递给带有地图的查询以执行它。此查询在 Oracle SQL 上运行正常,但在 H2 中未成功。
DAO
@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 上执行此查询时,它 returns:
错误
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 指定哪种数据类型是, 但 none 两者都有效。
为什么不起作用?有谁知道?提前致谢。
编辑:
StatusEnum
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 issue I raised中提供)是替换
SYSDATE - ?
和
SYSDATE - CAST(? AS INTEGER)
我已经检查过了,它适用于 H2 和 Oracle。
对于整数参数(Spring 数据)有解决方法:包含参数并添加 0
:
@Query(value = "DELETE FROM my_table WHERE update_ts < SYSDATE - (:days + 0)")
void cleanup(@Param("days") Integer days);
我正在使用 namedQuery,这对我有用。如果它可以帮助别人。
CAST(:variable AS double)
为了尊重休眠类型,它必须是小写的: https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#mapping-types-basictypes
@Luke 的解决方案有效,但我不得不改为小写