英次郎の辞書データをOracleDBに挿入する part2

#始めに
英次郎の辞書データをOracleのテーブルに挿入した時の手順を記載します
今回は、前回作成したHTMLファイルから単語情報を抜き出し、DBにインサートするとこまで記載します

#HTMLファイルの情報解析
##やりたいこと
やりたいことを端的に書くと
1. Jsoupを使ってtrタグ要素に属するテキスト情報を取得する
2. 1.で取得したテキスト情報をQuerryRunnerのbatchメソッドで実行できる型（Object[])に変換する
3. 1.,2.で作成したList\<Objects[]\>のリストを1万件ずつinsertする
です

##実装
```WordInserter.java
package word;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jsoup.Jsoup;
import word.sql.WordDictionarySql;

public class WordInserter {

	private static String WORD_DICTIONARY =
			"C:/Users/*****/Desktop/puisan_102.txt";
	private static int LIMMIT = 10000;

	public static void main(String args[])throws Exception{
    	long start = System.currentTimeMillis();
    	System.out.println("List作成処理を開始します");
		List <Object[]>list =getDictionarySource()
				.stream().collect(Collectors.toList());
		long end = System.currentTimeMillis();
    	System.out.println("List作成処理が完了しました");
		System.out.println(String.format("処理時間 %d秒",(end-start)/1000));
		
    	start = System.currentTimeMillis();
    	System.out.println("DB処理を開始します");
		OperateDB.createConnection();
		operateList(list);
		end = System.currentTimeMillis();
    	System.out.println("DB作成処理が完了しました");
		System.out.println(String.format("処理時間 %d秒",(end-start)/1000));
		OperateDB.closeConnection();
	}
	
	//Jsoupを使ってHTMLタグを解析し、結果をリストにする関数
	public static List<Object[]> getDictionarySource(){
		try{
			return Jsoup.parse(new File(WORD_DICTIONARY),"UTF-8")
					//タグ trに属する子要素をすべて取得する
					.getElementsByTag("tr") 
					.stream()
					//タグ trに属する子要素のテキストを取得し、
					//map関数を使ってDBにインサートできるデータ構造
					//(この場合はObject[])に変換する
					.map(s->new DictionaryWord(
							s.getAllElements().eachText()).params)
					//QueryLinnerのbatchでインサートできるようにList<Object[]>
					//に集約する
					.collect(Collectors.toList());
		}catch(Exception e){
			e.printStackTrace();
			return new ArrayList<Object[]>();
		}
    }
	
	//引数で渡されたListに対して、1万件単位でInsert処理を実行する
	public static void operateList(List<Object[]> word){
    	Stream.iterate(1, s->s+1)
    	.limit((int)Math.ceil(word.size()/LIMMIT))
    	.forEach(i->executeSQL(word,i));
	}
	
    public static void executeSQL(List<Object[]>list,int from){
    	if(list.size()<((from+1)*LIMMIT))
    		WordDictionarySql.insertToWordDictionary(
    				list.subList(from*LIMMIT, list.size()));
    	else 
    		WordDictionarySql.insertToWordDictionary(
    				list.subList((from-1)*LIMMIT, from*LIMMIT));
    }
	
	public static class DictionaryWord{
		public long wordIndex;
		public int wordLevel;
		public String word;
		public String searchWord;
		public String meaning;
		public String shortVer;
		public Object[] params=new Object[6];
		
		public DictionaryWord(List<String>list){
			this.wordIndex = Long.parseLong(list.get(1));
			params[0] = this.wordIndex;
			this.wordLevel = Integer.parseInt(list.get(3).replaceAll("■", ""));
			params[1] = this.wordLevel;
			this.word = list.get(2);
			params[2] = this.word;
			this.searchWord = list.get(2).toLowerCase();
			params[3] = this.word;
			this.meaning = list.get(4);
			params[4] = this.meaning;
			this.shortVer = list.get(4).length()>1000?
					list.get(4).substring(0,1000):list.get(4);
			params[5] = this.shortVer;
		}
		public String toString(){
			String format = "wordIndex=%d  wordLevel=%d "
					+ "word=%s meaning=%s shortVer=%s ";
			return String.format(format,this.wordIndex,this.wordLevel, 
					this.word,this.meaning,this.shortVer);
		}
	}
}
```
##雑感
Jsoupの解析結果として作られるDOMとJava8のStream関数の相性が良すぎてびっくりしてます
Stream関数がなければとてもじゃないけど、Javaで実装しようなんて思わなかったかも
(その場合は、rubyあたりを使っていたと思いますが）


#DBへの挿入処理
##やりたいこと
引数でもらったList\<Ojbect[]\>のlistを[前回の記事](http://qiita.com/triple4649/items/cd6d4e654e9c00de7e42)で作ったOperateDB#insertに渡すだけです

##実装
```WordDictionarySql.java
package word.sql;

import java.util.List;
import word.OperateDB;

public class WordDictionarySql {
	
    public static String INSERT_SQL = "insert into WORD_DICTIONAY "
    		+ "(WORD_INDEX,WORD_LEVEL,WORD,SEARCH_WORD,MEANING,SHORT_VER) values(?,?,?,?,?,?)";
    
    public static void insertToWordDictionary(List<Object[]> word){
    	try{
    		OperateDB.insert(word,INSERT_SQL);
    	}catch(Exception e){
    		e.printStackTrace();
    		throw new RuntimeException("DBのインサート処理でエラーが発生しました");
    	}
    }
}
```
##感想
約33万件のデータをOracleのテーブルに投入しましたが、実行時間は102秒程度でした
ちなみに,autocommitを有効にしている場合は、実行時間が230秒と倍程度かかっていました
autocommitを有効するとパフォーマンスが落ちる、ということを数字の上からも実感することができました