1. 序章

この記事では、プレーンJDBCを使用してデータベースにnull値を格納する方法を検討します。 null 値を使用する理由を説明することから始め、次にいくつかのコード例を示します。

2. null値の使用

null は、すべてのプログラミング言語を超越するキーワードです。 これは特別な値を表します。nullには値がない、または何も表さないというのが一般的な認識です null がデータベース列に格納されているということは、ハードディスクにスペースが予約されていることを意味します。 適切な値が利用可能になれば、そのスペースに格納できます。

別の認識は、nullがゼロまたは空白の文字列に等しいということです。 特定のコンテキストでのゼロまたは空白の文字列は、たとえば、倉庫内のゼロアイテムを意味する場合があります。 また、これら2つの値に対して、sumconcatなどの操作を実行できます。 ただし、 null を処理する場合、これらの操作は意味がありません。

null 値を使用してデータの特殊なケースを表すことには、多くの利点があります。 これらの利点の1つは、ほとんどのデータベースエンジンがnull値をsumavgなどの内部関数から除外することです。 一方、 null がコードに含まれている場合は、欠落している値を軽減するための特別なアクションをプログラムできます。

null をテーブルに追加すると、いくつかの欠点もあります。 null 値を含むデータを処理するコードを作成する場合、そのデータを別の方法で処理する必要があります。 これにより、見栄えの悪いコード、混乱、バグが発生する可能性があります。 また、 null 値は、データベース内で可変長にすることができます。 Integer列とByte列に格納されているnullの長さは異なります。

3. 実装

この例では、H2インメモリデータベースを備えた単純なMavenモジュールを使用します。 他の依存関係は必要ありません。

まず、Personという名前のPOJOクラスを作成しましょう。 このクラスには4つのフィールドがあります。 データベースの主キーとして使用されるId name、および lastName、は文字列であり、ageIntegerとして表されます年齢は必須フィールドではなく、nullにすることができます:

public class Person {
    private Integer id;
    private String name;
    private String lastName;
    private Integer age;
    //getters and setters
}

このJavaクラスを反映するデータベーステーブルを作成するには、次のSQLクエリを使用します。

CREATE TABLE Person (id INTEGER not null, name VARCHAR(50), lastName VARCHAR(50), age INTEGER, PRIMARY KEY (id));

これらすべてが邪魔にならないので、今、私たちは私たちの主な目標に集中することができます。 null値をInteger列に設定するには、PreparedStatementインターフェースで2つの定義された方法があります。

3.1. setNullメソッドの使用

setNull method、を使用すると、SQLクエリを実行する前に、フィールド値がnullであることを常に確認できます。 これにより、コードの柔軟性が高まります。

列インデックスを使用して、は、基になる列タイプに関する情報もPreparedStatementインスタンスに提供する必要があります。 この場合、これはjava.sql.Types.INTEGERです。

このメソッドは、null値に対してのみ予約されています。 それ以外の場合は、PreparedStatementインスタンスの適切なメソッドを使用する必要があります。

@Test
public void givenNewPerson_whenSetNullIsUsed_thenNewRecordIsCreated() throws SQLException {
    Person person = new Person(1, "John", "Doe", null);

    try (PreparedStatement preparedStatement = DBConfig.getConnection().prepareStatement(SQL)) {
        preparedStatement.setInt(1, person.getId());
        preparedStatement.setString(2, person.getName());
        preparedStatement.setString(3, person.getLastName());
        if (person.getAge() == null) {
            preparedStatement.setNull(4, Types.INTEGER);
        }
        else {
            preparedStatement.setInt(4, person.getAge());
        }
        int noOfRows = preparedStatement.executeUpdate();

        assertThat(noOfRows, equalTo(1));
    }
}

getAgeメソッドがnullを返し、null値を指定してsetIntメソッドを呼び出すかどうかを確認しない場合、NullPointerExceptionが発生します。

3.2. setObjectメソッドの使用

setObject メソッドでは、コード内の欠落データを処理する柔軟性が低くなります。 持っているデータを渡すことができ、基礎となる構造はJavaオブジェクトタイプをSQLタイプにマップします。

すべてのデータベースで、SQLタイプを指定せずにnullを渡すことができるわけではないことに注意してください。 たとえば、JDBCドライバはnullからSQLタイプを推測できません。

このメソッドを安全に使用するには、SQLタイプをsetObjectメソッドに渡すのが最善です。

@Test
public void givenNewPerson_whenSetObjectIsUsed_thenNewRecordIsCreated() throws SQLException {
    Person person = new Person(2, "John", "Doe", null);

    try (PreparedStatement preparedStatement = DBConfig.getConnection().prepareStatement(SQL)) {
        preparedStatement.setInt(1, person.getId());
        preparedStatement.setString(2, person.getName());
        preparedStatement.setString(3, person.getLastName());
        preparedStatement.setObject(4, person.getAge(), Types.INTEGER);
        int noOfRows = preparedStatement.executeUpdate();

        assertThat(noOfRows, equalTo(1));
    }
}

4. 結論

このチュートリアルでは、データベースでのnull値の基本的な使用法について説明しました。 次に、プレーンJDBCを使用してnull値をInteger列内に格納する方法の例を示しました。

いつものように、すべてのコードはGitHubにあります。