Talendのデータ型によくある問題のトラブルシューティング
この記事では、Talendのデータ型で作業する際によくある問題を回避する方法を説明します。
Talend Studioでのタイプマッピングの詳細は、タイプのマッピングをご覧ください。
通常のデータ型
Numbers
Javaとデータベースのベンダーでは、提供している数値実装が異なります。JDBCドライバーであれば、データを失うことなく移行できます。
ただし、それが必ずしも可能ではない型もあります。浮動小数点数や二重浮動小数点数は、正確な値を保持できません。これらの数値に対して数学的操作を行うと、操作の順序に基づいて異なる結果がもたらされます。好ましいプラクティスとしては、小さな数値を要約してから大きな数値を加算することです。
よくあるもう1つの間違いは、globalMap
を使う時です。プリミティブの代わりにクラスを使う必要があります。
int
>Integer
double
>Double
文字列を数値に変換する場合は、以下を使用します:
Integer.valueOf
/Integer.parseInt
Double.valueOf
/Double.parseDouble
Date
java.util.Date
とjava.sql.Date
はタイムスタンプを保持します。tLogRowコンポーネントは、設定したパターンに基づいてそのようなタイムスタンプを表示します。パターンにYYYY
しか含まれていない場合でも、基礎となるデータオブジェクトにはより多くの情報が含まれています。タイムゾーンは見落とされがちな情報の一例で、その結果、予想外に日付が動いてしまうことがあります。
たちえば、あるデータベースは2021-03-10 Midnight
という日付を返すものの、もう一方のデータベースはこれを2021-03-10 Midnight in Central Europe GMT+2
として扱い、UTCに変換して保存し、取り込んだ後に2021-03-09
となる日付型に変換します。これはしばしばバグとみなされますが、論理的な説明があります。
データベースは、オブジェクトを2021-03-10
として保存します。
これはJavaに送られ、(使用する変換に応じて)次のようになります。
2021-03-10 00:00:00.000 UTC
2021-03-10 02:00:00.000 GMT+2
次にデータベースに送られ、次のように処理されます:
2021-03-10 00:00:00.000 GMT+2
2021-03-09 22:00:00.000 UTC
UTCに変換すると、日付が1日繰り上がります。そのため、日付に関連する問題が発生した場合は常に日付全体(タイムゾーン、時間、秒)を分析する必要があります。
精度
Talendはjava.util.Date
を使用しているので、マイクロ秒やナノ秒の精度は利用できません。ただし、コンポーネントによっては、入力されるObject型がjava.sql.Timestamp
であるかどうかをチェックする場合があります。その場合はナノ秒単位も利用できます。この単位を使用するためには、スキーマ定義でObject型を選択し、ソースとターゲットのコンポーネントでこれをサポートする必要があります。
実行する価値がある実験
どのような問題でも、トラブルシューティングとして次の方法を試すことができます:
- tFileOutputコンポーネントを使い、その値をダンプして読み取る。こうすることで、タイムゾーンをコントロールしやすくなります。
Duser.timezone
パラメーターを使い、動作が変わるかどうか確認する。詳細は、Time Zone Settings in the JREををご覧ください。- これらのタイムゾーンの扱い方については、JDBCドライバーのドキュメンテーションをご覧ください。
- 以下のパターンと結果を持つtLogRowコンポーネントを使用する:
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX" 2001-07-04T12:08:56.235-07:00
ターゲットデータベースは、タイムゾーンと組み合わさった前の例のタイムスタンプ部分を保存できる場合もできない場合もあります。それによって日数がずれる可能性があります。
可能な回避策
Strings型を使い、データベースやそのドライバーが変換を処理できるかどうかを確認します。String型であれば、表示されているものがそのまま得られるので、他の隠れた情報はありません。
tJavaRowコンポーネントでJavaコードを使い、タイムゾーンを変換します。
String pattern = "yyyy-MM-dd";
log.info(TalendDate.formatDate(pattern, input_row.startDate));
output_row.startDateUTC = TalendDate.parseDateInUTC("yyyy-MM-dd zzz",
TalendDate.formatDate("yyyy-MM-dd", input_row.startDate)+" UTC");
データ動作の詳細は、Your Calendrical Fallacy Is...をご覧ください。
byte[] / binary
このデータ型は、画像、BLOB、その他のバイナリデータで最もよく使われます。
ただし、コンポーネントによっては、文字列として表現されるBase64エンコードのバイナリ形式を処理する場合もあります。この型に関連する最も一般的な間違いは、代わりにオブジェクトが使用された時です。その場合はログに@[aaa123
のように表示されますが、これはオブジェクトで.toString()
が使用された時にオブジェクト値ではなくオブジェクトIDが返されるためです。
Object
このデータ型の別の名前はOther
です。このデータ型は、上記で説明したJavaのあらゆるデータ型を表すことができます。これは、特殊な型(たとえばタイムスタンプなど)を表す場合に便利です。
ただし、利用可能なすべての情報にアクセスするためには、元の型にキャストする必要があります。
Comparison
==
形式による比較をサポートしています。ただし、他のデータ型(Stringなど)は.equals()
ファンクションや.compareTo()
ファンクションを使って比較する必要があります。
よくある間違い:
context.value == "foo"
は動作しません。
context.value.equals("foo")
はNullPointerExceptionを引き起こす可能性があります。ただし、"foo".equals(context.value)
は値がnullであればfalseになります。
特殊なデータ型
Snowflake - Geography型
SnowflakeはGeography (地理空間)型をサポートしています。ただし、Talendはこのデータ型をサポートしていません。
Strings型をGeography型に変換する詳細は、SnowflakeのドキュメンテーションでGeospatial Data Typesをご覧ください。
TO_GEOGRAPHYファンクションを自動的に適用すれば、スキーマを作成し、tFixedFlowInputコンポーネントを使ってデータをテストできます。
上記のように入力スキーマを定義し、地理空間データを以下のStringで表します:
POINT(-122.35 37.55)
Snowflakeテーブルゲームは次のように定義されます:
create table "SAMPLEGEO" (str1 text, str2 geography, int1 number);
tSnowflakeOutputBulkExecコンポーネントを使用すると、次のようになります:
SnowflakeではTalendのString型がGeography型に変換されることに注意してください。
String型またはObjectデータ型を使用している場合は、特殊型や奇妙なデータ型がデータベースにロードできるかどうか、常に確認する価値があります。