JdbcTemplate queryForInt / Long在Spring 3.2.2中已弃用。应该用什么代替?


104

Spring 3.2中不推荐使用JdbcTemplate中的queryforInt / queryforLong方法。我找不到使用这些方法替换现有代码的最佳实践的理由或理由。

典型方法:

int rowCount = jscoreJdbcTemplate.queryForInt(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    playerNameKey.toUpperCase(),
    teamNameKey.toUpperCase()
);

确定以上方法需要重新编写如下:

Object[] params = new Object[] { 
   playerNameKey.toUpperCase(), 
   teamNameKey.toUpperCase()
};
int rowCount = jscoreJdbcTemplate.queryForObject(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    params, Integer.class);

显然,这种弃用使JdbcTemplate类更简单(或者呢?)。QueryForInt一直是一种便捷的方法(我想),并且已经存在了很长时间。为什么将其删除。结果,代码变得更加复杂。



您是对的,我不知道为什么我的消息来源没有@Deprecated
Sotirios Delimanolis 2013年

将Spring版本更新到3.2.2-似乎在这里第一次被弃用
Dan MacBean 2013年

我将现有的代码库从3.1升级到3.2.2,并且这些方法在各处都得到了使用。需要了解为什么以及如何更新代码。
Dan MacBean 2013年

请注意,queryForObject可能会返回null(在您的示例中情况并非如此)。我发现没有其他方法可以复制现在来自queryForInt / Long的空检查代码。
hochraldo

Answers:


110

我认为是有人意识到queryForInt / Long方法具有令人困惑的语义,也就是说,从JdbcTemplate源代码中可以看到其当前实现:

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    Number number = queryForObject(sql, args, Integer.class);
    return (number != null ? number.intValue() : 0);
}

这可能会导致您认为如果结果集为空,则将返回0,但是会引发异常:

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

因此,以下实现实质上与当前实现等效:

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    return queryForObject(sql, args, Integer.class);
}

然后,现在必须将不推荐使用的代码替换为丑陋的代码:

    queryForObject(sql, new Object { arg1, arg2, ...}, Integer.class);

或这个(更细):

    queryForObject(sql, Integer.class, arg1, arg2, ...);

12
那不是真的 第三个代码段不等于实现!因为有一个自动装箱的隐藏NPE。如果查询返回结果,但它们为null,则先前的代码将返回0而不是null-为了正确地重现先前的行为,它将是:Integer result = queryForObject(sql,args,Integer.class); 返回结果== null?0:结果;
MetroidFan2002

@ MetroidFan2002:确实,您的观察是对的!但是,从API设计的角度来看,如果查询仅返回一个NULL值,我相信最好按原样返回它,而不是假设NULL(如queryForInt那样)等于0。这是工作API用户评估此类条件的能力。
加百利·贝林格勒

问题是,如果并且当用户将NPE放在那里时,除非他们在其环境中明确设置了某些东西(例如Eclipse可以选择突出显示自动装箱的选项),否则该行上的NPE看起来就像JDBCOperations实例一片空白。以前,将返回零。现在,为什么要在返回null的查询中使用它,我也不知道(这主要是由于n00bs这样做了,他们会这样做),但是将其删除并不是IMO的重大举措。
MetroidFan2002

我发现一个可能的原因是由于不准确。我有一个长值10000000233174211由queryForLong(String)返回,但是相反,它返回的是10000000233174212,即+1。我查看了代码,将Double转换为Long,因此转换可能存在一些问题。
mrswadge

再想一想我的评论,该列的数据类型为number(19,0),所以也许这就是为什么double起作用的原因?我还是通过使用queryForObject(sql,Long.class)解决了这个问题。
mrswadge 2015年

35

我同意最初的说法,即不赞成使用便捷方法queryForLong(sql)带来的不便。

我使用Spring 3.1开发了一个应用程序,并且刚刚将其更新为最新的Spring版本(3.2.3),并注意到它已被弃用。

幸运的是,这对我来说只是一行更改:

return jdbcTemplate.queryForLong(sql);  // deprecated in Spring 3.2.x

改为

return jdbcTemplate.queryForObject(sql, Long.class);

而且一些单元测试似乎表明,上述更改有效。


好点子。没有括号也可以正常工作。:)
SGB 2015年

14

不推荐使用queryForObject(String, Class)


13

替换这样的代码:

long num = jdbcTemplate.queryForLong(sql);

使用此代码:

long num = jdbcTemplate.queryForObject(sql, Long.class);

这是非常危险的,因为如果列具有null值,则queryForObject返回null,并且我们知道原始类型不能为null,并且您将具有NullPointerException。编译器没有对此发出警告。您将在运行时知道此错误。如果您有返回原始类型的方法,则会遇到相同的错误:

public long getValue(String sql) {
    return = jdbcTemplate.queryForObject(sql, Long.class);
}

Spring 3.2.2中JdbcTemplate中不推荐使用的方法queryForLong具有以下主体:

@Deprecated
public long queryForLong(String sql) throws DataAccessException {
    Number number = queryForObject(sql, Long.class);
    return (number != null ? number.longValue() : 0);
}

您会看到在它们返回原始值之前,要检查它是否不为null,如果为null,则它们返回0。顺便说一句-应该为0L。


3
2美分:如果启用了自动装箱警告,则编译器可能会警告您。
keiki 2014年

我不知道 谢谢队友:)
Marcin Kapusta 2014年

2

JdbcTemplate#queryForInt如果列值为SQL NULL或0,则返回0。无法将一种情况与另一种情况区分开。我认为这是不推荐使用该方法的主要原因。顺便说一句,ResultSet#getInt行为类似。不过,我们可以通过区分这两种情况ResultSet#wasNull


-1
public int getCircleCount() {
    Object param = "1";
    String sql = "select count(*) from circle where id = ? ";
    jdbcTemplate.setDataSource(getDataSource());
    int result = getJdbcTemplate().queryForObject(sql, new Object[] { param }, Integer.class);
    return result;
}

请解释您的答案。
严厉的沃丹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.