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

しゃってん [E-MAIL ADDRESS DELETED]
2010年 10月 22日 (金) 15:32:27 JST


しゃってんです。

> 普通に更新で entity.setXxx(null) して更新してみて下さい。
こちらの環境で実行した場合もNullPointerException が発生しました。

TnValueTypes.registerBasicValueType(keyType, new UtilDateAsTimestampType() {
       @Override
       public void bindValue(PreparedStatement ps, int index, Object
value) throws SQLException {
           if (value==null) {
               ps.setNull(index, java.sql.Types.TIMESTAMP);
           } else {
               ps.setObject(index, new
oracle.sql.DATE(DfTypeUtil.toTimestamp((java.util.Date) value)));
               //super.bindValue(ps, index, value);
           }
       }
    }); // switch

とすることでNullPointerException は回避はできますね。


2010年10月22日14:41 kubo <[E-MAIL ADDRESS DELETED]>:
> 久保(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 mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-user
>


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