データベースをOracleからPostgresに変更するにあたっての対応方法

962 views
Skip to first unread message

s.dot.s...@gmail.com

unread,
Aug 11, 2016, 10:57:19 AM8/11/16
to DBFluteユーザの集い
はじめて投稿します。

杉本と申します。

利用しているのは、
・DBFlute 0.9.6.9
・Java 6
・Seasar2.4
です。

利用しているデータベースをOracle10gからPostgres9.2に変更します。
それにあたり、null・空文字の扱いがDBごとに異なるため
その部分をどう吸収しようか検討しています。

postgresに変わることで null と 空文字があることで、 
is null の条件、order by(nulls first) 等への影響があるため
oracleと同じ動き(※1)をさせた方がDB変更による影響が少ないだろうと
思っています。

※1:DB上は空文字を存在させないようにし、nullの状態にしておく。

そこで考えているのは、

1)
littleAdjustmentMap.dfprop の isEntityConvertEmptyStringToNull をtrueにして
自動生成(generate.bat)を実行してエンティティを再生成することで
convertEmptyToNullでの処理が変わり、空文字ならばnullが返却されるコードが
自動生成されることは確認済です。

再生成されたエンティティを利用すれば、insert/update において 空文字はnullでDBに登録され、
select結果のエンティティもnullになる動作のため、DB変更前のoracleのときと変わらない
使い方ができるのではと思っています。

2)
isEntityConvertEmptyStringToNull =falseのままの場合は、

ImplementedCommonColumnAutoSetupper にて、entityを引数にとるため、そのentityクラスにて
リフレクションを利用して、プロパティの型をチェックして、String(DB上はvarcharやchar)型の場合に、
長さ0の空文字だった場合にentityのプロパティのセッターをリフレクションで呼び出してnullにする
という方法をとろうと思っていますが、他に良い方法はありますでしょうか?

3)
DBFlute関連での対応でなく、SAStrutsを利用しているため、
S2RequestProcessorを拡張してActionFormのインスタンス生成後、Actionクラスへの
ActionFormのインジェクション前後あたりで、リフレクション等でStringのプロパティを
nullに書き換える。
ただ、List<String>、Mapや、配列、ActionFormの中にネストしたクラスがある場合など
考慮する点が多そうなのと、ActionFormのバリデーションが空文字をnullにコンバートした
前や後などどちらにすべきかといったことで、・・・・考慮点が多そうなので、3)は
採用しない方が良いかなと思っています。


なお、外出しのsqlファイルは、修正が必須なので修正します。
例えば、
- NVLからの変更でCOALESCE等の利用
- サブクエリのエイリアス指定の追加
- is null / is not null の条件は空文字が入る場合は、変更が必要だが、DB上で空文字は存在させない。
- 文字列連結の  col1 || col2 で、どちらかがnullとなる場合はCOALESCE等の利用して空文字に返還しておく
- Order by での nulls first はOralceもpostgresも同じ挙動だが、空文字が混在すると、 
 空文字の順序はnullと同じではないため順序が変わる

oracleからpostgresへのデータ移行は、ora2pg というのを使う予定です。

上記の1)と外出しsqlファイルを適宜修正していく方針と思っていますが、
他に良さそうな方法や、DBFluteをつかっていてOracle→postgresに変更した際の対応例など
ありますでしょうか。


よろしくお願いします。

kubo

unread,
Aug 12, 2016, 10:28:10 AM8/12/16
to DBFluteユーザの集い
jfluteです

杉本さん、こんばんは

DBFluteご利用ありがとうございます。
かなり深く調べられているようですので、
非常に答えやすいです。

まあ、基本的には1の、
「littleAdjustmentMap.dfprop の isEntityConvertEmptyStringToNull をtrueにして」
がDBFlute的にはオススメです。

2は、かなり強引な手法なので、1がうまく動いているなら、
2をやる必要はないように思えます。

3は、プログラム上色々と修正する箇所が多々出てくると想像します。
空文字で動いていたところが null になって落ちるとか。
ちょうどぼくはLastaFlute作っているので、
その辺 null にするために色々な考慮が後から
どんどん出てくるだろうと想像します。

加えて杉本さんに言う通り、外だしSQLを気をつけるという感じですね。
まあ、DBに空文字さえ入らなければ、nulls first とか、
あんまり気にしなくてよくなるはずですので、
とにかくDBに空文字を入れないことが大切ですね。

あと当然ですが、DBFlute以外のツールからアクセスしているアプリが
あったら、そこも気をつけないとですね。

> DBFluteをつかっていてOracle→postgresに変更した際の対応例など
> ありますでしょうか。

ちょっとぼくはその移行は経験ないので…

MLご覧のみなさんで Oracle to PostgreSQL への移行を
したことのある方いらっしゃいましたら、
何かコメント頂ければと思います。

s.dot.s...@gmail.com

unread,
Aug 14, 2016, 12:41:45 PM8/14/16
to DBFluteユーザの集い
杉本です。

jfluteさん、返信ありがとうございます。


>まあ、基本的には1の、 

>「littleAdjustmentMap.dfprop の isEntityConvertEmptyStringToNull をtrueにして」 
>がDBFlute的にはオススメです。 

やはり 空文字を入れないようにするには、
設定&自動生成で対応できるため、1を採用ですね。


>まあ、DBに空文字さえ入らなければ、nulls first とか、 
>あんまり気にしなくてよくなるはずですので、 
>とにかくDBに空文字を入れないことが大切ですね。 

>あと当然ですが、DBFlute以外のツールからアクセスしているアプリが 
>あったら、そこも気をつけないとですね。 

空文字を何らかしら入れてしまうようなことがないようにしないといけないですね。
・データ移行時での空文字でなくnullにしておくこと。(ora2pgというツールでは、nullでのインポート用データが生成されるようでした)
・運用者がOracleに慣れていて、postgresを扱ったことがないことが想定されるため
 運用上のツールや手動でSQL運用しているような箇所は事前に洗い出す
 

よろしくお願いします。


2016年8月12日金曜日 23時28分10秒 UTC+9 jflute:

kubo

unread,
Aug 15, 2016, 12:47:47 AM8/15/16
to DBFluteユーザの集い
jfluteです

> >「littleAdjustmentMap.dfprop の isEntityConvertEmptyStringToNull をtrueにして」
> >がDBFlute的にはオススメです。
>
> やはり 空文字を入れないようにするには、
> 設定&自動生成で対応できるため、1を採用ですね。

ちなみにですが、身の回りのプロジェクトでは、
MySQLを使っていてもこのオプションは必ず有効にしています。
空文字とnullが混在して嬉しいことほぼないので。

そして、LastaFlute というフレームワークの Example デフォルトでも、
このプロパティが true の状態で環境構築されます。

# でも、DBFluteのデフォルトにするのはやり過ぎなので、
# そこはそのまま空文字とnullは与えられた通りに動きます。


なんだかんだ、アプリを作り直さずにDBMSを変えるって、
あんまり情報がないので、
もし何かDBFlute周りで特徴的なことがあったら、
気軽に情報共有して頂けると嬉しいです(^^。
Reply all
Reply to author
Forward
0 new messages