3

春まであと数日。Spring-JDBC を Web アプリケーションに統合します。DB で CRUD 操作を正常に実行でき、ボイラープレート コードの削減に感銘を受けました。しかし、query*()で提供されているメソッドを使用できませんNamedParameterJDBCTemplateRowMapperインターネット上のほとんどの例では、またはの使用法が示されていますResultSetExtractor。どちらの使用法も問題ありませんが、これらのインターフェイスを実装する必要があるクラスを作成する必要があります。DBにロードするすべてのタイプのデータに対してBeanを作成する必要があります(または、間違っている可能性があります)。

次のようなものを使用したコードセクションで問題が発生します。

String query="select username, password from usertable where username=?"
ps=conn.prepareStatement(query);
ps.setString(username);
rs=ps.executeQuery();

if(rs.next()){
    String username=rs.getString("username");
    String password=rs.getString("password")

    //Performs operation on them
}  

これらの値はどの Bean にも保存されず、直接使用されるため、このような状況で jdbcTemplate を統合することはできません。Bean に存在するプロパティの一部のみをデータベースから抽出しているときに、別の状況が発生します。例:

public class MangaBean{
    private String author;
    private String title;
    private String isbn;
    private String releaseDate;
    private String rating;

    //getters and setters

} 

マッパー:

public class MangaBeanMapper implements RowMapper<MangaBean>{

    @Override
    public MangaBean mapRow(ResultSet rs, int arg1) throws SQLException {
        MangaBean mb=new MangaBean();
        mb.setAuthor(rs.getString("author"));
        mb.setTitle(rs.getString("title"));
        mb.setIsbn(rs.getString("isbn"));
        mb.setReleaseDate(rs.getString("releaseDate"));
        mb.setRating(rs.getString("rating"));
        return mb;
    }
}

上記の配置は、次のようにうまく動作します。

String query="select * from manga_data where isbn=:isbn"
Map<String, String> paramMap=new HashMap<String, String>();
paramMap.put("isbn", someBean.getIsbn());
return template.query(query, paramMap, new MangaBeanMapper());

ただし、データベースから 2 つまたは 3 つの値のみを取得したい場合、上記のパターンはBadSqlGrammarException: releaseDate does not exist in ResultSet. 例 :

String query="select title, author where isbn=:isbn"
Map<String, String> paramMap=new HashMap<String, String>();
paramMap.put("isbn", someBean.getIsbn());
return template.query(query, paramMap, new MangaBeanMapper());

テンプレートは のインスタンスですNamedParameterJDBCTemplate。これらの状況の解決策を教えてください。

4

4 に答える 4

3

他の答えは賢明です:DTO Beanを作成するか、を使用する必要がありBeanPropertyRowMapperます。

ただし、BeanPropertyRowMapperよりも詳細な制御が必要な場合(またはリフレクションによって速度が遅くなりすぎる場合)は、

queryForMap

メソッド。返された列をキーとしてマップのリスト(行ごとに1つ)を返します。例外をスローせずにマップを呼び出すことができるためget(/* key that is not there */)(nullが返されるだけです)、選択した列に関係なく、同じコードを使用してオブジェクトにデータを設定できます。

于 2012-12-20T15:31:26.923 に答える
2

独自の RowMapper を記述する必要さえありません。Spring が提供するBeanPropertyRowMapperを使用するだけです。これが機能する方法は、Bean のプロパティに返される列名と一致することです。クエリには、Bean と正確に一致する列があります。そうでない場合は、次のように選択で as を使用します...

-- This query matches a property named matchingName in the bean
select my_column_that doesnt_match as matching_name from mytable;

BeanPropertyRowMapperは、リストした両方のクエリで動作するはずです。

于 2012-12-20T15:09:38.180 に答える
1

通常、 yes : ほとんどのクエリでは、結果を変換する Bean またはオブジェクトを作成します。ほとんどの場合、それはあなたがやりたいことです。

ただし、次のように、結果セットを Bean ではなくマップにマップする RowMapper を作成できます。欠点は、Bean のタイプ管理が失われることであり、各列の正しいタイプを返すために jdbc ドライバーに依存することになります。

@NimChimpskey が投稿したばかりのように、小さな Bean オブジェクトを作成するのが最善ですが、本当にそれをしたくない場合は、これが別のオプションです。

  class SimpleRowMapper implements RowMapper<Map<String, Object>> {
    String[] columns;

    SimpleRowMapper(String[] columns) {
      this.columns = columns;
    }

    @Override
    public Map<String, Object> mapRow(ResultSet resultSet, int i) throws SQLException {
      Map<String, Object> rowAsMap = new HashMap<String, Object>();
      for (String column : columns) {
        rowAsMap.put(column, resultSet.getObject(column));
      }
      return rowAsMap;
    }
  }
于 2012-12-20T13:48:06.800 に答える
1

最初の例では、DTO Bean/Value オブジェクトを作成してそれらを格納します。一般的に実装されているパターンには理由があります。コーディングに数分かかり、多くの長期的なメリットがあります。

2番目の例では、フィールドを設定しないrowmapperの2番目の実装を作成するか、必要に応じてマンガビーンにnull/代入値を指定します:

    @Override
    public MangaBean mapRow(ResultSet rs, int arg1) throws SQLException {
    MangaBean mb=new MangaBean();
    mb.setAuthor(rs.getString("author"));
    mb.setTitle(rs.getString("title"));
   /* mb.setIsbn("unknown");*/
    mb.setReleaseDate("unknown");
    mb.setRating(null);
    return mb;
    }
于 2012-12-20T13:45:24.137 に答える