[Talend]tMysqlBulkExecを使う時はスキーマの設定を忘れずに

talend

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

TalendのtMysqlBulkExecはファイルを読み込んでDB(Mysql)に登録してくれる
便利なコンポーネントです。
tMysqlBulkExecを使っていて少しハマった点があったので、
同じ過ちを繰り返さないためにもブログに残しておきます。

環境

今回の環境は以下の通りです。

  • Windows8.1 64bit
  • Talend Open Studio 6.2.0
  • Java 1.8
  • MySQL 5.7.10

tMysqlBulkExecを使ってみる

普通に使ってみます。
次のようなテーブルを作成し、データを入れるためのCSVファイルを用意しました。

create table sample( 
  id int not null
  , name varchar (256) not null
  , created_date datetime not null
  , primary key (id)
); 
1,"サンプルデータ1",2016/07/07 07:07:07
2,"サンプルデータ2",2016/07/08 08:08:08
3,"サンプルデータ3",2016/07/09 09:09:09

ジョブと呼んでいいのかわかりませんが、今回はコンポーネント1つを配置するだけです。
talend2016070701
基本設定タブのテーブルにデータを挿入したいテーブル名、読込対象にローカルファイル名に対象のファイルを設定します。
詳細設定タブには、読込むファイルに合わせた記述をしておきます。
talend2016070702
talend2016070703
これだけでジョブを実行すれば、ファイルを読み込んで中身をDBに登録してくれます。

テーブルを作成してくれない

コンポーネントの基本設定タブにテーブルの操作という箇所があります。
ファイルを読み込んでデータを入れる際には、基本的にはテーブルがあらかじめ作られている前提だとは思います。
とはいえファイルがあればTalendが新しくテーブル作ってくれるなら便利だと思ったので、試してみることにしました。
上で用意したCSVファイルをコピーしsample2data.csvを作成し、テーブルは作成しないままジョブを実行します。
talend2016070704
すると以下のようなテーブルが存在しないというエラーが発生します。

Exception in component tMysqlBulkExec_1
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'devdb.sample2' doesn't exist
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
	at com.mysql.jdbc.Util.getInstance(Util.java:387)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:939)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2547)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2505)
	at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:840)
	at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:740)
	at test001.job_0_1.Job.tMysqlBulkExec_1Process(Job.java:357)
	at test001.job_0_1.Job.runJobInTOS(Job.java:610)
	at test001.job_0_1.Job.main(Job.java:467)

ちなみに『テーブルの作成』を選んだ場合と『何もしない』を選んだ場合のソースコードを比較してみた所、全く変化はありませんでした。

スキーマを設定すればテーブルは作られる

talend2016070705
ここで少々ハマりましたが、スキーマを設定したところソースコードにも変化があり、CREATE文が追加されました。

				java.sql.Statement stmtCreate_tMysqlBulkExec_1 = conn_tMysqlBulkExec_1
						.createStatement();

				stmtCreate_tMysqlBulkExec_1
						.execute("CREATE TABLE `"
								+ tableName_tMysqlBulkExec_1
								+ "`(`id` INT(11)   not null ,`name` VARCHAR(256)   not null ,`create_date` DATETIME  not null ,primary key(`id`))");

				stmtCreate_tMysqlBulkExec_1.close();

				// in mysql when autoCommit=true don't commit.
				if (!conn_tMysqlBulkExec_1.getAutoCommit()) {
					conn_tMysqlBulkExec_1.commit();
				}

スキーマを設定してあげないとテーブル作成するための情報がないので、正しくテーブルが作成されないようですね。
テーブルがあれば、特にスキーマを設定せずとも問題がなかったので失念しておりましたが、tMysqlBulkExecを使うときはスキーマを設定しましょう。

おわりに

今回ソースコードを見て何かおかしいことに気付けたので、ソースコードを書く必要性の薄いTalendの場合でも何かおかしい動きがあったらコードを見てみてもいいと思います(自動生成されたコードは読みにくいですが)。
実はスキーマを設定する際にも長さを指定するのを忘れていて少しハマってました(その時もコード見て何かが足りないことに気づけました)。
とりあえず、また一つTalendについて学べました。