JdbcTemplate queryForInt / Longは、Spring 3.2.2で非推奨になりました。何に置き換える必要がありますか?


104

JdbcTemplateのqueryforInt / queryforLongメソッドは、Spring 3.2では非推奨です。これらの方法を使用して既存のコードを置き換えるためのベストプラクティスと見なされている理由や理由がわかりません。

典型的な方法:

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 '27 / 03/13

Springバージョンを3.2.2に更新しました-最初にここで廃止されたようです
Dan MacBean

既存のコードベースを3.1から3.2.2にアップグレードし、これらの方法は至る所で使用されています。コードを更新する理由と方法を理解する必要があります。
Dan MacBean 2013年

queryForObjectが返される可能性があることに注意してくださいnull(この例ではそうではありません)。queryForInt / Longのnullチェックコードを複製する以外に方法はありませんでした。
hochraldo 2013

回答:


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
それは真実ではありません。3番目のコードスニペットは実装とは異なります!自動ボックス化解除を備えた非表示のNPEがあるためです。クエリが結果を返したがそれらがnullの場合、前のコードはnullではなく0を返します。以前の動作を適切に再現するには、次のようになります。Integer result = queryForObject(sql、args、Integer.class); 結果を返す== null?0:結果;
MetroidFan2002

@ MetroidFan2002:確かにあなたの観察は本当です!ただし、API設計の観点からは、クエリがNULL値を1つだけ返す場合は、(queryForIntが行うように)NULLが0と同等であると想定するのではなく、そのまま返す方が良いと思います。そのような条件を評価するためのAPIユーザーの。
Gabriel Belingueres 2013

問題は、ユーザーがNPEをそこに取得したときに、環境で特定のものを明示的に設定しない限り(たとえば、Eclipseにはオートボクシングの使用を強調表示するオプションがある)、その行のNPEがJDBCOperationsインスタンスのようになることです。無効です。以前は、ゼロが返されていました。これで、nullを返すクエリでこれを使用する理由がわかりません(これは基本的にn00bsが実行するためです)、これらを削除することはIMOの大きな動きではありません。
MetroidFan2002 2013

考えられる理由は、不正確なためです。queryForLong(String)から返される長い値10000000233174211がありましたが、代わりに10000000233174212、つまり+1を返していました。コードを調べたところ、DoubleからLongに変換されたため、変換に問題がある可能性があります。
mrswadge 2015年

上記の私のコメントを少し考えてみると、列のデータ型はnumber(19,0)だったので、これがdoubleが登場した理由かもしれません。とにかくqueryForObject(sql、Long.class)を使用して問題を回避しました。
mrswadge

35

便利なメソッドqueryForLong(sql)を廃止することは不便であるという元の投稿者に同意します。

私はSpring 3.1を使用してアプリを開発し、最新のSpringバージョン(3.2.3)にアップデートしたところ、廃止されていることに気付きました。

幸い、私にとっては1行の変更でした。

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セント:オートボクシング警告を有効にすると、コンパイラが警告を表示する場合があります。
ケイキ14

私はそれについて知りませんでした。ありがとうメイト:)
Marcin Kapusta 2014

2

JdbcTemplate#queryForInt列の値がSQL NULLまたは0の場合は0を返します。大文字と小文字を区別する方法はありません。これがメソッドが廃止された主な理由だと思います。ところで、ResultSet#getInt同様に動作します。ただし、これら2つのケースはで区別でき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;
}

あなたの答えを説明してください。
過酷なウォーダン2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.