Spring Boot DB連携

OracleのIN句で1000件を超える項目を指定してみた

Oracleデータベースの場合、IN句で1000件を超える項目を指定するとエラーになってしまうので、注意が必要である。

今回は、Spring Bootアプリケーション内でMyBatisフレームワークを利用する状態で、OracleのIN句で1000件の項目を指定した場合と、1000件を超える項目を指定した場合の動作を確認してみたので、共有する。

前提条件

下記記事の実装が完了していること。

MyBatisフレームワーク内で引数のリストからIN句を自動生成してみたSpring Bootアプリケーション内でDBアクセス処理を含む場合に、MyBatisフレームワークを利用することがあるが、foreac...

PL/SQLによるデータ追加

Oracleデータベースに多数のデータを追加するには、PL/SQLブロックを利用すると便利である。user_dataテーブルのデータを削除し、1001件のデータを追加するPL/SQLプログラムの内容は、以下の通り。

begin
   execute immediate 'TRUNCATE TABLE user_data';
   for i in 1..1001 loop
      INSERT INTO user_data VALUES (i, 'テスト プリン' || TO_MULTI_BYTE(i), 2012, 1, 20, TO_CHAR(MOD(i, 2) + 1), 'テスト');
   end loop;
   COMMIT;
end;
/
データの追加_1

上記PL/SQLプログラムを実行後の、データ数、idの最小・最大値、追加データの一部を確認した結果は、以下の通り。

SELECT COUNT(*) FROM user_data
データの追加_2
SELECT MIN(id), MAX(id) FROM user_data
データの追加_3
SELECT * FROM user_data WHERE id <= 10
データの追加_4



サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから追加/変更したプログラムである。

application.propertiesの内容は以下の通りで、ログが見にくくなるため、SQLログ出力部分を削除している。

server.port = 8084
# DB接続先
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=USER01
spring.datasource.password=USER01
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver

また、Spring Bootのメインクラスの内容は以下の通りで、IN句に1000件のデータを追加しSQLを実行した場合、IN句に1001件のデータを追加しSQLを実行した場合の処理を追加している。

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.ArrayList;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    private UserDataMapper userDataMapper;

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

    @Override
    public void run(String... args) {
	    // IN句を指定したSQLの実行結果を確認する
        // 引数のIDリストに1000件のデータを指定した場合
        ArrayList<Long> idList = getIdListOneThousand();
        System.out.println("*** 引数のIDリストに1000件のデータを指定した場合 ***");
        System.out.println("*** idList size : " + idList.size());

        ArrayList<UserData> userDataList = userDataMapper.findByIdList(idList);
        System.out.println("*** userDataList size : " + userDataList.size());
        System.out.println();

        // 引数のIDリストに1001件のデータを指定した場合
        idList = getIdListOneThousandOne();
        System.out.println("*** 引数のIDリストに1001件のデータを指定した場合 ***");
        System.out.println("*** idList size : " + idList.size());
        try{
            userDataMapper.findByIdList(idList);
        }catch(Exception ex){
            System.out.println("*** " + ex.getCause());
        }
    }

    private ArrayList<Long> getIdListOneThousand(){
        ArrayList<Long> idList = new ArrayList<>();
        for(int i = 1; i <= 1000; i++){
            idList.add(Long.valueOf(i));
        }
	    return idList;
    }

    private ArrayList<Long> getIdListOneThousandOne(){
        ArrayList<Long> idList = getIdListOneThousand();
        idList.add(Long.valueOf(1001));
        return idList;
    }
}

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-oracle-in-over1000/demo



サンプルプログラムの実行結果

Spring Bootのメインクラス(DemoApplication.java)を実行した結果、コンソールログに出力される内容は以下の通り。
サンプルプログラムの実行結果

上記実行結果の青枠部分で、IN句に1000件のデータを追加した場合に正常にSQLが実行されることが、赤枠部分で、IN句に1001件のデータを追加した場合にOracleエラーが発生することが、それぞれ確認できる。

要点まとめ

  • Oracleデータベースの場合、IN句で1000件を超える項目を指定するとエラーになってしまうので、注意が必要である。