[Seasar-user:20275] Re: [DBFlute]OracleでDATE型カラムのインデックスが利用されない

kubo [E-MAIL ADDRESS DELETED]
2010年 10月 22日 (金) 14:41:40 JST


久保(jflute)です。

> ただその前に、もう一つお願いしたいです。
> oracle.sql.DATEを有効にした状態で、バッチ更新を使って、
> 該当のカラムを更新してみて下さい。
> 実はこちらで試してて、oracle.sql.Datum クラス内で
> NullPointerException が発生してしまいました。
バッチ更新ってわけじゃなく、該当カラムを
null で更新しようとすると発生するようです。
普通に更新で entity.setXxx(null) して更新してみて下さい。

2010/10/22 kubo <[E-MAIL ADDRESS DELETED]>:
> 久保(jflute)です。
>
> しゃってんさん、色々と検証ありがとうございます。
> 状況が随分はっきりしてきましたね。
> (小林さんのフォローに感謝感謝です)
>
>> littleAdjustmentMap.dfprop あたりでのオプション扱いとして、
>> 上記インナークラス部分を出力するような感じでもいいかもしれませんね。
>
> 勘がいいですねー。そういう感じのつもりです。
> ただその前に、もう一つお願いしたいです。
> oracle.sql.DATEを有効にした状態で、バッチ更新を使って、
> 該当のカラムを更新してみて下さい。
> 実はこちらで試してて、oracle.sql.Datum クラス内で
> NullPointerException が発生してしまいました。
> もしかしたら、検索条件のときだけ有効にするとか、
> バッチ更新では除外するとか、何かしら処理を入れる
> 必要があるのかもしれません。
>
> 2010/10/22 しゃってん <[E-MAIL ADDRESS DELETED]>:
>>> ((OraclePreparedStatement) ps).setDATE(index, new DATE(date));
>> #
>> # org.seasar.extension.dbcp.impl.ConnectionPoolImpl を利用している場合、
>> # Connection connection =
>> ((ConnectionWrapperImpl)dataSource.getConnection()).getPhysicalConnection();
>> # としないとClassCastExceptionとなるんですね。。。
>> #
>> で実行した場合、時刻まで考慮された検索結果が取得され
>> INDEX RANGE SCAN で検索が実行されました。
>>
>>
>> 同様に
>>> TnValueTypes.registerBasicValueType(keyType, new UtilDateAsTimestampType() {
>>>    @Override
>>>    public void bindValue(PreparedStatement ps, int index, Object
>>> value) throws SQLException {
>>>        ps.setObject(index, new
>>> DATE(DfTypeUtil.toTimestamp((java.util.Date) value)));
>>>        //super.bindValue(ps, index, value);
>>>    }
>>> }); // switch
>> #
>> # SQLの組み立て時にFromToOption を利用すると時刻の指定ができなかったので
>> # cb.query().setTargetDate_GreaterEqual(fromDate);
>> # cb.query().setTargetDate_LessThan(toDate);
>> # に変更しています。
>> #
>> の場合も時刻が考慮された検索結果が取得され、
>> INDEX RANGE SCAN で検索が実行されました。
>>
>> littleAdjustmentMap.dfprop あたりでのオプション扱いとして、
>> 上記インナークラス部分を出力するような感じでもいいかもしれませんね。
>> ※あとFromToOptionで無変換で返すクラスがあればいいかなと。
>>
>>
>> 2010年10月22日3:24 kubo <[E-MAIL ADDRESS DELETED]>:
>>> 久保(jflute)です。
>>>
>>> しゃってんさん、まだDBFluteとしてどうするか考え中ですが、
>>> DBFluteConfig にて、
>>>
>>> TnValueTypes.registerBasicValueType(keyType, valueType); // switch
>>>
>>>>>>
>>> TnValueTypes.registerBasicValueType(keyType, new UtilDateAsTimestampType() {
>>>    @Override
>>>    public void bindValue(PreparedStatement ps, int index, Object
>>> value) throws SQLException {
>>>        ps.setObject(index, new
>>> DATE(DfTypeUtil.toTimestamp((java.util.Date) value)));
>>>        //super.bindValue(ps, index, value);
>>>    }
>>> }); // switch
>>>
>>> に差し替えて試してみて下さい。
>>> (「DATE」は、oracle.sql.DATE です)
>>> 恐らく、java.sql.Date を指定したときと同じ実行結果に
>>> なるんじゃないかと思われます。
>>> こちらでも、30万件のテーブルを用意して比べてみると、
>>> 安定してパフォーマンスが改善されます。
>>> (30万件程度なのでわずかですが10msほど安定して差がでます)
>>>
>>> ※これをどう整理して提供するかがポイントですね...
>>>
>>> 2010/10/21 kubo <[E-MAIL ADDRESS DELETED]>:
>>>> 久保(jflute)です。
>>>>
>>>>>> O/Rマッパには厳しい話ですね。。。
>>>>>> いっそリフレクションでガツンってのは
>>>>>> やはり無理矢理過ぎるかなぁ。
>>>>>
>>>>> リフレクションでガツンとは?
>>>>
>>>> コンパイルレベルでDBMSのJDBCに依存したくないので、
>>>> リフレクションで oracle.sql.DATE を利用するように処理する
>>>> って感じですね。(もちろん、Oracleの場合に限り)
>>>>
>>>> 自動生成ありきのツールなので、oracle.sql.DATE を利用する
>>>> ValueType を自動生成するのが現実的かもと今考えています。
>>>> (OracleのDATE型の場合はそのValueTypeを使う)
>>>> アプリは基本的にOracleのJDBCに依存しても問題ないので。
>>>> (一応、オプションで)
>>>>
>>>> 2010/10/21 Koichi Kobayashi <[E-MAIL ADDRESS DELETED]>:
>>>>> 小林 (koichik) です.
>>>>>
>>>>> Date:    Thu, 21 Oct 2010 20:52:00 +0900
>>>>> From:    kubo <[E-MAIL ADDRESS DELETED]>
>>>>> To:      [E-MAIL ADDRESS DELETED]
>>>>> Subject: [Seasar-user:20268] Re: [DBFlute]OracleでDATE型カラムのインデックスが利用されない
>>>>>
>>>>>> なるほど、そもそもDBMSに依存しないJDBCの型の中で、
>>>>>> Oracle の DATE 型をぴったし当てはめられる型が存在しない
>>>>>> というところですかね。
>>>>>
>>>>> そうですね.
>>>>> JDBC および標準 SQL には日時 (日付と時刻) を
>>>>> 扱うデータ型が基本的に TIMESTAMP 1 種類
>>>>> (TZ 等は精度と同じ扱いとして) しかないのに対し,
>>>>> Oracle には DATE と TIMESTAMP の 2 種類があり,
>>>>> どちらも java.sql.Timestamp にマッピングするのが
>>>>> 問題の根本でしょうね.
>>>>> 歴史的なものなのでしょうがないですけど.
>>>>>
>>>>>> DATE型カラムのメタデータが:
>>>>>>   ojdbc5.jar = java.sql.Types.DATE
>>>>>>   ojdbc6.jar = java.sql.Types.TIMESTAMP
>>>>>> となっていたので TIMESTAMP の指定で問題ないかなと
>>>>>> 思ったのですが、(実際検索の動きとしては問題ないですが)
>>>>>> 内部的には型違いと。
>>>>>
>>>>> Oracle の DATE が java.sql.Types.DATE なのは
>>>>> 単純に間違ってますよね.
>>>>> Oracle の DATE は日付型ではなく日時型なので.
>>>>> ただし,Oracle の日時型には 2 種類ある...
>>>>>
>>>>>> > Oracle JDBC ドライバには oracle.sql.DATE という
>>>>>> > 型があるので、java.sql.Timestamp からこの型に
>>>>>> > 変換して、OraclePreparedStatement#setDATE() に
>>>>>> > 渡すなんてのが Oracle 的に好ましいやり方なのかも。
>>>>>>
>>>>>> O/Rマッパには厳しい話ですね。。。
>>>>>> いっそリフレクションでガツンってのは
>>>>>> やはり無理矢理過ぎるかなぁ。
>>>>>
>>>>> リフレクションでガツンとは?
>>>>>
>>>>>
>>>>> S2JDBC でも同じ問題は起こり得るので
>>>>> 何か考えた方がいいかなぁ.
>>>>> 幸い (?),S2JDBC では
>>>>>
>>>>> @Temporal(TemporalType.TIMESTAMP)
>>>>> public java.util.Date xxx;
>>>>>
>>>>> public java.sql.Timestamp xxx;
>>>>>
>>>>> という 2 種類の書き方ができるので,前者の場合は
>>>>> DATE,後者の場合は TIMESTAMP にマップして,
>>>>> 前者は OracleDialect で oracle.sql.DATE に
>>>>> 変換するとか.
>>>>> S2JDBC-Gen と辻褄合うのかなぁ...
>>>>>
>>>>>
>>>>> --
>>>>> <component name="koichik">
>>>>>    <property name="fullName">"Koichi Kobayashi"</property>
>>>>>    <property name="email">"[E-MAIL ADDRESS DELETED]"</property>
>>>>>    <property name="blog">"http://d.hatena.ne.jp/koichik"</property>
>>>>>    <property name="twitter">"http://twitter.com/koichik"</property>
>>>>> </component>
>>>>>
>>>>> _______________________________________________
>>>>> 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 mailing list
>> [E-MAIL ADDRESS DELETED]
>> https://ml.seasar.org/mailman/listinfo/seasar-user
>>
>


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