[Seasar-user:14721] Re: [dbflute]idの自動採番について

Chihiro Ueta [E-MAIL ADDRESS DELETED]
2008年 6月 17日 (火) 09:26:53 JST


久保様、おはようございます。

植田です。お世話になります。
ご丁寧に教えて頂き、本当にありがとうございます。

> S2TestCase#readXlsReplaceDb()は利用しておりませんが、
> DBFluteのReplaceSchemaを利用してテストデータを投入して
> いて、全く同じ現象が発生しました。
:
> 「現在のテーブルに入っているIDのMAXをsetval()」
> する処理をreadXlsReplaceDb()を実行したときに
> 一緒に実行されるように仕掛けることで回避できるかと思います。
> S2TestCaseを継承したそのプロジェクト独自の抽象TestCaseを
> 作成し、そこでこの処理を入れるのが良いかと思います。

抽象TestCaseで「現在のテーブルに入っているIDのMAXをsetval()」する方法で
テストを行い、現象を回避することが出来ました。
ReplaceSchemaで作成しているテストデータも同じように、教えて頂いた方法を
真似させてもらいます。ありがとうございます。

> はい、これに関しては、PostgreSQLのserial型は特別扱いで
> Sequence設定を省略できるようにしてあるだけなので、
> 明示的に設定しても特に何も変わりません。
> http://dbflute.sandbox.seasar.org/contents/dbvendor/postgresql.html

すみません。上記、確認しました。

以上、宜しくお願い致します。

kubo さんは書きました:
> 久保です。
> 
> 植田さん、こんばんは
> 
> 下記の件、自分も悩んだことがあります。
> 
> S2TestCase#readXlsReplaceDb()は利用しておりませんが、
> DBFluteのReplaceSchemaを利用してテストデータを投入して
> いて、全く同じ現象が発生しました。
> 
>  1. replace-schema.batを実行
>   1-1. playsql/replace-schema.sqlでCreateTable&Sequence
>   1-2. playsql/data配下のデータが登録される
>     →ここではSequence利用しないで登録(1,2,3,4,5...)
> 
>  2. JUnitからinsert()
>   →Sequenceが1から始まるので例外
> 
> 自分は、この手順の中に
> 「現在のテーブルに入っているIDのMAXをsetval()」
> する処理を含めて回避できました。
> 
>  1. replace-schema.batを実行
>   1-1. playsql/replace-schema.sqlでCreateTable&Sequence
>   1-2. playsql/data配下のデータが登録される
>     →ここではSequence利用しないで登録(1,2,3,4,5...)
>   1-3. playsql/take-finally.sqlでsetval() {★}
>     →「現在のテーブルに入っているIDのMAXをsetval()」
>     →テストデータ投入後に実行される(take-finally.sql)
> 
>  2. JUnitからinsert()
>   →SequenceがMaxの次から始まるので正常動作
> 
> そのplaysql/take-finally.sqlは実際にこれです。
> 
> // DBFlutePostgreSQLExample
> https://www.seasar.org/svn/sandbox/dbflute/trunk/dbflute-postgresql-example/dbflute_exampledb/playsql/take-finally.sql
> 
> select setval('member_member_id_seq', (select max(member_id) from member));
> select setval('member_login_member_login_id_seq', (select
> max(member_login_id) from member_login));
> select setval('product_product_id_seq', (select max(product_id) from product));
> select setval('purchase_purchase_id_seq', (select max(purchase_id)
> from purchase));
> 
> ※serial型のSequenceを利用しています。
> 
> 
> このように
> 「現在のテーブルに入っているIDのMAXをsetval()」
> する処理をreadXlsReplaceDb()を実行したときに
> 一緒に実行されるように仕掛けることで回避できるかと思います。
> S2TestCaseを継承したそのプロジェクト独自の抽象TestCaseを
> 作成し、そこでこの処理を入れるのが良いかと思います。
> 
> (もしくは、手間でなければテストデータを100万台から
>  始めるというのも手です。テストを100万回実行しない限り
>  落ちることはないはずです。が、ちょっと気持ち悪い気もします)
> 
>> 「work」のテーブルの ID のカラムは SERIAL8 で作成し、Sequence設定は行っ
>> ておりません。
>> 試しにSequence設定で以下のような設定を行いましたが、insert時に振られるID
>> はやはり 1 から始まりました。
> 
> はい、これに関しては、PostgreSQLのserial型は特別扱いで
> Sequence設定を省略できるようにしてあるだけなので、
> 明示的に設定しても特に何も変わりません。
> http://dbflute.sandbox.seasar.org/contents/dbvendor/postgresql.html
> 
> 
> 2008/6/16 Chihiro Ueta <[E-MAIL ADDRESS DELETED]>:
>> 植田と申します。
>> いつもお世話になっております。
>>
>> dbfluteのインサート時のIDの自動割り当てについて質問させてください。
>>
>> 以下のような環境で使用させて頂いております。
>> DB:PostgreSQL8.1
>> jdbc:8.3-603.jdbc3
>> dbflute:0.7.1
>> s2-framework:2.4.24
>> s2dao:1.0.47
>>
>> S2Unitで、S2TestCase#readXlsReplaceDb("エクセルファイル") を利用したテス
>> トを行っております。
>> 「work」のテーブルのテストを行うためにエクセルファイルには、ID(primary
>> key)が 1 から 5 までのテストデータを「work」のテーブルに登録しておりま
>> す。テストには「work」テーブルの外部参照テーブルを含めたいため、エクセル
>> ファイルにはID(primary key)も指定しております。
>> 「work」テーブルに対してdbfluteのWorkBhv#insertのテストを実行した場合
>> に、ID が 1 から始まってしまうため、下のようなプライマリキーが重複してい
>> るというエラーが発生します。この場合のテストを成功させるために、何か良い
>> 方法はないでしょうか?設定内容などについて注意点などが御座いましたらご助
>> 言頂けませんでしょうか?
>>
>> --------エラー内容--------
>> org.seasar.framework.exception.SQLRuntimeException: [ESSR0072]SQLで例外
>> (SQL=[INSERT INTO work ("省略") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
>> ?, ?, ?, ?, ?, ?)], Message=[[ESSR0072]SQLで例外(SQL=[INSERT INTO work
>> ("省略") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)],
>> Message=[0], ErrorCode=23505, SQLState={3})が発生しました : [SQLで例外
>> (Message=[ERROR: duplicate key violates unique constraint "work_pkey"],
>> ErrorCode=0, SQLState=23505)が発生しました。], [ERROR: duplicate key
>> violates unique constraint "work_pkey"], ErrorCode=0, SQLState=23505)が
>> 発生しました
>> --------------------------
>>
>> 再度テストを実行すると、自動で割り当てられるIDは 2 になります。
>> これを繰り返すと、IDは1づつ大きくなっていき、6 になったときにテストに成
>> 功します。
>>
>> 「work」のテーブルの ID のカラムは SERIAL8 で作成し、Sequence設定は行っ
>> ておりません。
>> 試しにSequence設定で以下のような設定を行いましたが、insert時に振られるID
>> はやはり 1 から始まりました。
>>
>> dfprop/sequenceDefinitionMap.dfprop
>>
>> map:{
>>    ; work     = work_id_seq
>> }
>>
>> 以上、宜しくお願い致します。
>>
>> _______________________________________________
>> Seasar-user mailing list
>> [E-MAIL ADDRESS DELETED]
>> https://ml.seasar.org/mailman/listinfo/seasar-user
>>
> _______________________________________________
> Seasar-user mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-user
> 
> 
> 



Seasar-user メーリングリストの案内