Oracleデータベースの場合、IN句で1000件を超える項目を指定するとエラーになってしまうので、注意が必要である。
今回は、Spring Bootアプリケーション内でMyBatisフレームワークを利用する状態で、OracleのIN句で1000件の項目を指定した場合と、1000件を超える項目を指定した場合の動作を確認してみたので、共有する。
前提条件
下記記事の実装が完了していること。
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; /
上記PL/SQLプログラムを実行後の、データ数、idの最小・最大値、追加データの一部を確認した結果は、以下の通り。
SELECT COUNT(*) FROM user_data
SELECT MIN(id), MAX(id) FROM user_data
SELECT * FROM user_data WHERE id <= 10
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、前提条件のプログラムから追加/変更したプログラムである。
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件を超える項目を指定するとエラーになってしまうので、注意が必要である。