Spring JDBC

Spring JDBC

1. 概要

この記事では、SpringJDBCモジュールの実際の使用例について説明します。

Spring JDBCのすべてのクラスは、4つの個別のパッケージに分割されています。

  • core –JDBCのコア機能。 このパッケージの重要なクラスには、JdbcTemplateSimpleJdbcInsert,SimpleJdbcCall、およびNamedParameterJdbcTemplateが含まれます。

  • datasource –データソースにアクセスするためのユーティリティクラス。 また、Java EEコンテナの外部でJDBCコードをテストするためのさまざまなデータソース実装があります。

  • object –オブジェクト指向の方法でのDBアクセス。 クエリを実行し、結果をビジネスオブジェクトとして返すことができます。 また、ビジネスオブジェクトの列とプロパティ間でクエリ結果をマップします。

  • supportcoreおよびobjectパッケージの下のクラスのクラスをサポートします。 E.g. SQLException変換機能を提供します。

    ==さらに読む:

Spring Security:JDBC認証の調査

既存のDataSource構成を使用してJDBC認証を実行するために、Springが提供する機能を調べてください。

Spring Data JPAの紹介

Spring 4を使用したSpring Data JPAの概要-Spring構成、DAO、手動および生成されたクエリとトランザクション管理。

2. 設定

まず、データソースの簡単な構成から始めましょう(この例ではMySQLデータベースを使用します)。

@Configuration
@ComponentScan("com.example.jdbc")
public class SpringJdbcConfig {
    @Bean
    public DataSource mysqlDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/springjdbc");
        dataSource.setUsername("guest_user");
        dataSource.setPassword("guest_password");

        return dataSource;
    }
}

別の方法として、開発またはテストに組み込みデータベースを活用することもできます。これは、H2組み込みデータベースのインスタンスを作成し、簡単なSQLスクリプトを事前に設定するクイック構成です。

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
      .setType(EmbeddedDatabaseType.H2)
      .addScript("classpath:jdbc/schema.sql")
      .addScript("classpath:jdbc/test-data.sql").build();
}

最後に、もちろん、datasourceのXML構成を使用して同じことを行うことができます。


    
    
    
    

3. JdbcTemplateと実行中のクエリ

3.1. 基本的なクエリ

JDBCテンプレートは、関心のあるほとんどの機能にアクセスするためのメインAPIです。

  • 接続の作成と終了

  • ステートメントとストアドプロシージャコールの実行

  • ResultSetを繰り返し、結果を返す

まず、JdbcTemplateで何ができるかを確認するための簡単な例から始めましょう。

int result = jdbcTemplate.queryForObject(
    "SELECT COUNT(*) FROM EMPLOYEE", Integer.class);

また、簡単なINSERTもあります。

public int addEmplyee(int id) {
    return jdbcTemplate.update(
      "INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)", id, "Bill", "Gates", "USA");
}

?文字を使用してパラメーターを提供する標準構文に注意してください。 次へ–この構文の代替案を見てみましょう。

3.2. 名前付きパラメーターを使用したクエリ

support for named parametersを取得するには、フレームワークによって提供される他のJDBCテンプレートであるNamedParameterJdbcTemplateを使用します。

さらに、これはJbdcTemplateをラップし、「?」を使用してパラメーターを指定する従来の構文の代替手段を提供します。 内部的には、名前付きパラメーターをJDBC「?」に置き換えます。プレースホルダーと、ラップされたJDCTemplateに委任して、クエリを実行します。

SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("id", 1);
return namedParameterJdbcTemplate.queryForObject(
  "SELECT FIRST_NAME FROM EMPLOYEE WHERE ID = :id", namedParameters, String.class);

MapSqlParameterSourceを使用して、名前付きパラメーターの値を提供していることに注目してください。

たとえば、Beanのプロパティを使用して名前付きパラメータを決定する以下の例を見てみましょう。

Employee employee = new Employee();
employee.setFirstName("James");

String SELECT_BY_ID = "SELECT COUNT(*) FROM EMPLOYEE WHERE FIRST_NAME = :firstName";

SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(employee);
return namedParameterJdbcTemplate.queryForObject(
  SELECT_BY_ID, namedParameters, Integer.class);

以前のように名前付きパラメーターを手動で指定する代わりに、BeanPropertySqlParameterSource実装をどのように利用しているかに注意してください。

3.3. クエリ結果のJavaオブジェクトへのマッピング

もう1つの非常に便利な機能は、the RowMapperインターフェースを実装することにより、クエリ結果をJavaオブジェクトにマップする機能です。

たとえば、クエリによって返されるすべての行に対して、Springは行マッパーを使用してJava Beanに値を設定します。

public class EmployeeRowMapper implements RowMapper {
    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        Employee employee = new Employee();

        employee.setId(rs.getInt("ID"));
        employee.setFirstName(rs.getString("FIRST_NAME"));
        employee.setLastName(rs.getString("LAST_NAME"));
        employee.setAddress(rs.getString("ADDRESS"));

        return employee;
    }
}

その後、行マッパーをクエリAPIに渡して、完全に入力されたJavaオブジェクトを取得できます。

String query = "SELECT * FROM EMPLOYEE WHERE ID = ?";
List employees = jdbcTemplate.queryForObject(
  query, new Object[] { id }, new EmployeeRowMapper());

4. 例外翻訳

Springには、すぐに使用できる独自のデータ例外階層が付属しており、ルート例外としてDataAccessExceptionが使用され、基になるすべての生の例外がSpringに変換されます。

そのため、低レベルの永続性例外を処理する必要がなく、Springが低レベルの例外をDataAccessExceptionまたはそのサブクラスの1つでラップするという事実から利益を得ることで、健全性を維持します。

また、これにより、使用している基礎となるデータベースから独立した例外処理メカニズムが維持されます。

さらに、デフォルトのSQLErrorCodeSQLExceptionTranslatorに加えて、SQLExceptionTranslatorの独自の実装を提供することもできます。

これはカスタム実装の簡単な例です。重複するキー違反がある場合にエラーメッセージをカスタマイズします。これにより、H2を使用するとerror code 23505が発生します。

public class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTranslator {
    @Override
    protected DataAccessException
      customTranslate(String task, String sql, SQLException sqlException) {
        if (sqlException.getErrorCode() == 23505) {
          return new DuplicateKeyException(
            "Custom Exception translator - Integrity constraint violation.", sqlException);
        }
        return null;
    }
}

このカスタム例外トランスレータを使用するには、setExceptionTranslator()メソッドを呼び出してJdbcTemplateに渡す必要があります。

CustomSQLErrorCodeTranslator customSQLErrorCodeTranslator =
  new CustomSQLErrorCodeTranslator();
jdbcTemplate.setExceptionTranslator(customSQLErrorCodeTranslator);

5. SimpleJdbcクラスを使用したJDBC操作

SimpleJdbcクラスは、SQLステートメントを構成および実行する簡単な方法を提供します。 これらのクラスは、データベースメタデータを使用して基本的なクエリを作成します。 SimpleJdbcInsertおよびSimpleJdbcCallクラスは、挿入およびストアード・プロシージャー呼び出しを実行するためのより簡単な方法を提供します。

5.1. SimpleJdbcInsert

最小限の構成で単純な挿入ステートメントを実行する方法を見てみましょう。

The INSERT statement is generated based on the configuration of SimpleJdbcInsertで必要なのは、テーブル名、列名、値を指定することだけです。

まず、SimpleJdbcInsertを作成しましょう。

SimpleJdbcInsert simpleJdbcInsert =
  new SimpleJdbcInsert(dataSource).withTableName("EMPLOYEE");

次に、列の名前と値を指定して、次の操作を実行します。

public int addEmplyee(Employee emp) {
    Map parameters = new HashMap();
    parameters.put("ID", emp.getId());
    parameters.put("FIRST_NAME", emp.getFirstName());
    parameters.put("LAST_NAME", emp.getLastName());
    parameters.put("ADDRESS", emp.getAddress());

    return simpleJdbcInsert.execute(parameters);
}

さらに、database to generate the primary keyを許可するために、executeAndReturnKey()APIを利用できます。また、自動生成される実際の列を構成する必要があります。

SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
                                        .withTableName("EMPLOYEE")
                                        .usingGeneratedKeyColumns("ID");

Number id = simpleJdbcInsert.executeAndReturnKey(parameters);
System.out.println("Generated id - " + id.longValue());

最後に–BeanPropertySqlParameterSourceMapSqlParameterSource.を使用してこのデータを渡すこともできます

5.2. SimpleJdbcCallのストアドプロシージャ

また、ストアドプロシージャの実行を見てみましょう。SimpleJdbcCallの抽象化を利用します。

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource)
                             .withProcedureName("READ_EMPLOYEE");
public Employee getEmployeeUsingSimpleJdbcCall(int id) {
    SqlParameterSource in = new MapSqlParameterSource().addValue("in_id", id);
    Map out = simpleJdbcCall.execute(in);

    Employee emp = new Employee();
    emp.setFirstName((String) out.get("FIRST_NAME"));
    emp.setLastName((String) out.get("LAST_NAME"));

    return emp;
}

6. バッチ操作

別の単純なユースケース-複数の操作をまとめてバッチ処理します。

6.1. JdbcTemplateを使用した基本的なバッチ操作

JdbcTemplate, Batch Operationsの使用は、batchUpdate()APIを介して実行できます。

ここで興味深い部分は、簡潔ですが非常に便利なBatchPreparedStatementSetterの実装です。

public int[] batchUpdateUsingJdbcTemplate(List employees) {
    return jdbcTemplate.batchUpdate("INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)",
        new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                ps.setInt(1, employees.get(i).getId());
                ps.setString(2, employees.get(i).getFirstName());
                ps.setString(3, employees.get(i).getLastName());
                ps.setString(4, employees.get(i).getAddress();
            }
            @Override
            public int getBatchSize() {
                return 50;
            }
        });
}

6.2. NamedParameterJdbcTemplateを使用したバッチ操作

NamedParameterJdbcTemplatebatchUpdate()APIを使用して操作をバッチ処理するオプションもあります。

このAPIは、以前のAPIよりも単純です。パラメーター値を設定するための内部準備済みステートメントセッターがあるため、パラメーターを設定するための追加のインターフェイスを実装する必要はありません。

代わりに、パラメーター値をSqlParameterSourceの配列としてbatchUpdate()メソッドに渡すことができます。

SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(employees.toArray());
int[] updateCounts = namedParameterJdbcTemplate.batchUpdate(
    "INSERT INTO EMPLOYEE VALUES (:id, :firstName, :lastName, :address)", batch);
return updateCounts;

7. SpringBootを使用したSpringJDBC

Spring Bootは、リレーショナルデータベースでJDBCを使用するためのスターターspring-boot-starter-jdbcを提供します。

すべてのSpring Bootスターターと同様に、これもアプリケーションを迅速に起動して実行するのに役立ちます。

7.1. メーベン依存

プライマリの依存関係としてspring-boot-starter-jdbcの依存関係と、使用するデータベースの依存関係が必要になります。 この場合、これはMySQLです。


    org.springframework.boot
    spring-boot-starter-jdbc


    mysql
    mysql-connector-java
    runtime

7.2. 設定

Spring Bootは、データソースを自動的に構成します。 propertiesファイルでプロパティを提供する必要があります。

spring.datasource.url=jdbc:mysql://localhost:3306/springjdbc
spring.datasource.username=guest_user
spring.datasource.password=guest_password

これで、これらの構成のみを実行するだけで、アプリケーションが稼働し、他のデータベース操作に使用できるようになります。

標準のSpringアプリケーションの前のセクションで見た明示的な構成が、Spring Bootの自動構成の一部として含まれるようになりました。

8. 結論

この記事では、Spring JDBCが提供するさまざまな機能を実用的な例とともに取り上げ、Spring FrameworkのJDBC抽象化について説明しました。

また、Spring Boot JDBCスターターを使用してSpring JDBCをすばやく開始する方法を検討しました。

例のソースコードは利用可能なover on GitHubです。