[Talend]tMysqlBulkExecを使う時はスキーマの設定を忘れずに
はじめに
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つを配置するだけです。 基本設定タブのテーブルにデータを挿入したいテーブル名、読込対象にローカルファイル名に対象のファイルを設定します。 詳細設定タブには、読込むファイルに合わせた記述をしておきます。 これだけでジョブを実行すれば、ファイルを読み込んで中身をDBに登録してくれます。
テーブルを作成してくれない
コンポーネントの基本設定タブにテーブルの操作という箇所があります。 ファイルを読み込んでデータを入れる際には、基本的にはテーブルがあらかじめ作られている前提だとは思います。 とはいえファイルがあればTalendが新しくテーブル作ってくれるなら便利だと思ったので、試してみることにしました。 上で用意したCSVファイルをコピーしsample2data.csvを作成し、テーブルは作成しないままジョブを実行します。 すると以下のようなテーブルが存在しないというエラーが発生します。
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)
ちなみに『テーブルの作成』を選んだ場合と『何もしない』を選んだ場合のソースコードを比較してみた所、全く変化はありませんでした。
スキーマを設定すればテーブルは作られる
ここで少々ハマりましたが、スキーマを設定したところソースコードにも変化があり、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について学べました。