7月 132012
 

Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10):

For type byte, the default value is zero, that is, the value of (byte)0.

For type short, the default value is zero, that is, the value of (short)0.

For type int, the default value is zero, that is, 0.

For type long, the default value is zero, that is, 0L.

For type float, the default value is positive zero, that is, 0.0f.

For type double, the default value is positive zero, that is, 0.0d.

For type char, the default value is the null character, that is, ‘\u0000’.

For type boolean, the default value is false.

For all reference types (§4.3), the default value is null.

booleanはfalse、参照型はnull、その他プリミティブ型は0がデフォルト値。

7月 132012
 
  • JDBC APIではPreparedStatementインタフェースを用いてパラメタライズドクエリを実行する
  • OracleJDBCドライバではOraclePreparedStatementクラスを用いてパラメタライズドクエリを実行する
  • OraclePreparedStatementのsetStringメソッドおよびsetCharメソッドは空白埋めを行わない
  • OraclePreparedStatementのsetFixedCharメソッドは空白埋めを行う
  • JDBCのPreparedStatementインタフェースにはsetCharおよびsetFixedCharメソッドは定義されていない
    (これらはOracleのJDBC拡張機能を用いる事で実装できる)

要するに・・・

CHAR(5)型のCOL1列を持ったテーブルTABLE_Aに対して
[sql]SELECT * FROM TABLE_A WHERE COL1=?[/sql]
というSQLに比較文字列をバインドしてを発行する時、setString(1, "ABC")とするとCOL1='ABC'という比較がされ、確実に0件。
setString(1, "ABC ")としなければならない。

OracleParameterdStatement.setFixedChar(int, String)を使用することにより、空白埋め比較でバインドする事も出来るが、DBに依存したコードとなる。

ちなみにバインドをしないでリテラルで比較するとヒットする。
[sql]SELECT * FROM TABLE_A WHERE COL1=’ABC'[/sql]
これはOracleでは両辺にVARCHAR2型またはNVARCHAR2型が使用されている場合以外は、空白埋めで比較が行われるためである。

そもそも可変文字列の格納にCHAR型を使うのをやめればすむ話。。

参考:

7月 132012
 

※憶測入り。特にデシリアライズの時の判断基準とか適当。

結論から言うと、普通は指定しなくて大丈夫。
シリアライズする必要性のあるクラスの場合、指定したほうが環境問題に悩まされずにすむのでベター。

serialVersionUIDとわ

端的にいえば、シリアライズされたオブジェクトを送る側と受け取る側で、どのクラスのインスタンスなのかを識別するためのID。

いろいろ
  • どうやらクラス名とクラスメンバとserialVersionUID(以下SUID)で判別してるようだ。
  • 送られてきたクラス定義とSUIDが、受け取る側が参照できるクラスと同じなら、互換性があるクラスだと判断して、オブジェクトをそのクラスを使用して解析するんだと思う。
  • 定義とSUIDが同じだけど実は互換性がない(実装が違う)場合、変換時に例外が出る。
  • 指定しないとSHA-1でクラスのハッシュから計算されるっぽい。
  • SUID自動計算の方法は環境によって違うっぽいので自分で指定したほうがベター。
  • Serializableインタフェースだと勝手に計算してくれる。
  • Externalizableインタフェースだと自分で指定しないとだめぽい。
  • Exceptionの場合、ThrowableインタフェースがSerializableインタフェースを実装してるので、SUIDが求められる。
おまけ

serialverコマンドでSUID自動計算の結果が見れる。

ざっと試した感じ、以下の情報できまるっぽい。

  • クラス名
  • クラスのフィールド(プロパティ、メンバ変数)全部
  • private以外のメソッド

実装コードは関係なかった。
まぁシリアライズする必要性のあるクラスにはやはり自分で指定したほうがいいと思う。

参照
7月 132012
 
  • Oracle10gのJDBCは、DATE型項目の場合java.sql.Date型で返却するために時刻が欠落する。
  • Oracle9.0.1より前のJDBCではjava.sql.Timestamp型で返却していたため時刻は欠落しない。
  • Oracle11gもjava.sql.Timestamp型で返却する仕様をデフォルトとしているため時刻は欠落しない。

  • Oracle10gの場合、oracle.jdbc.V8Compatible=trueを指定することでjava.sql.Timestamp型で返却する動作となる。

参考:

Oracleオブジェクト型からSQL DATEデータ型へのマッピング

Oracle Database 8i以下のバージョンではTIMESTAMPデータがサポートされていませんでしたが、SQL標準への拡張機能として、Oracle DATEデータに時刻コンポーネントが含まれていました。このため、Oracle Database 8i以下のバージョンのJDBCドライバは、oracle.sql.DATEをjava.sql.Timestampにマップして時刻コンポーネントを保持していました。Oracle Database 9.0.1以上ではTIMESTAMPがサポートされ、9iのJDBCドライバがoracle.sql.DATEをjava.sql.Dateにマッピングするようになりました。このマッピングはOracle DATEデータの時刻コンポーネントを切り捨てたため、不正確でした。この問題を克服するために、Oracle Database 11.1では新しいフラグmapDateToTimestampが導入されました。このフラグのデフォルト値はtrueです。これは、デフォルトで、ドライバがoracle.sql.DATEをjava.sql.Timestampに正確にマップして時刻情報を保持することを意味します。不正確でも10gと互換性のあるoracle.sql.DATEからjava.sql.Dateへのマッピングが必要な場合は、mapDateToTimestampフラグの値をfalseに設定します。

注意:
oracle.sql.DATEからjava.sql.Dateへのマッピングの問題を克服するために、Oracle Database 9.2でフラグV8Compatibleが導入されました。このフラグのデフォルト値はfalseで、これはOracle DATEデータのjava.sql.Dateデータへのマッピングが許可されることを意味します。ただし、このフラグの値をtrueに設定することによって、ユーザーはOracle DATEデータの時刻コンポーネントを保持することができました。このフラグは11gでは非推奨です。これは、Oracle Database 8iとの互換性がサポートされなくなったためです。

Oracleからの回答:

QUESTION
======
oracle.jdbc.V8Compatible=trueにすることで getObject()の戻り値の型がDate→Timestamp と変更される以外に動作が変わることがあるか。

ANSWER
======
ございません。

oracle.jdbc.V8Compatible=true に設定することによる動作の変更点はgetObject()の戻り値の型が Date→Timestamp と変更されるだけでございます。

7月 132012
 

DBへの型のマッピングは気をつけないとダメだよという話。

予備知識とか
  • ANSI SQLのDATE型は日付のみ保持する。
  • OracleのDATE型は日付だけでなく時刻まで保持する。(秒未満の精度とタイムゾーンは保持しない)
DATE型@Java
  • java.sql.DateクラスはANSI準拠。日付までしか保持しない
  • java.util.Dateクラスはミリ秒まで保持する。
  • JDBCではjava.sql.DateクラスはDATE型(JDBC)にマッピングされる。
  • JDBCではjava.util.DateクラスはDATE、TIME、TIMESTAMP型(JDBC)にマッピングされる。
問題例とか
  • JavaでOracleに日付を登録する場合、やり方によっては時刻情報が落ちる。
  • java.sql.Dateのコンストラクタはlong型なミリ秒を受け取れるが、残るのは日付のみ。

参考:

7月 132012
 
現象

Cドライブ直下に”testdir “というディレクトリがある場合

[csharp]Directory.GetFiles(@”c:\testdir “);[/csharp]

という具合に検索すると見つからないといわれる。
ディレクトリ名末尾が全角スペースの場合も同様。

原因
[csharp]Directory.GetFiles(@”c:\testdir “);[/csharp]

と検索しても、実際に検索されるのは”c:\testdir”となるため。
空白をTrimしているっぽい。

回避策

検索するパスの末尾に”\”をつければ検索可能。

[csharp]Directory.GetFiles(@”c:\testdir\”);[/csharp]
参考

全角スペースがあるフォルダあるとSystem.IO.Directory.GetFilesがエラーになる: DOBON.NETプログラミング掲示板過去ログ

7月 132012
 
  • AuthzSVNAccessFileのグループはApacheのグループではなく[groups]を使う。
  • SVNParentPathディレクティブは、リポジトリ直下ではなく、複数リポジトリの親ディレクトリを指定する場合に使う。
  • SVNListParentPathをONにしないと、SVNParentPathで指定したディレクトリは403になる。
  • mod_auth_basic.soの認証とmod_authz_svn.soの認証は分けて考えたほうがわかりやすいかも。
    • mod_auth_basicで該当ロケーション以下のディレクトリをまとめてログイン認証。
    • mod_authz_svnで各リポジトリの各ディレクトリ単位でアクセス許可を設定。
    • つまり、BASIC認証通過後、その認証情報でSVNのアクセス権をチェックするイメージ。
      • アクセス権がなかったら403になる。
      • Eclipseではフォルダはリモートに存在しませんと出る。
  • AuthUserFile、AuthzSVNAccessFileの変更はApache再起動不要。
7月 132012
 
再現環境

サーバー:

  • CVSNT2.5.02
  • ワークグループを構成。ドメイン非参加。

クライアント:

  • Eclipse3.2.1
  • ドメインに参加している。

その他:

  • サーバークライアント間にルーターが2つある。
  • 各マシンに設定されているDNSサーバーは別。WINSサーバーは同じ。
現象

CVSNTに対してリモートからpserverでアクセスしたとき、ファイル一覧の取得などの動作が妙に遅い場合がある。
サーバーローカルから接続すると起きない。

原因

有効だがケーブルが接続されていないネットワーク接続設定があると遅くなるようだ。
恐らくクライアント名の解決で、使えないネットワークを見に行ってタイムアウトしているものと思われる。

クライアント側からサーバーとのやり取りのパケットを見ていると、認証OKのパケット(I LOVE YOUっていわれる!)を受け取るのに時間がかかっているのがわかる。(約4秒)

処置

使っていないネットワーク接続設定を無効にすれば解決する。
CVSNT Control PanelのAdvancedタブの”Don’t resolve client names (debug setting)”を有効にしても直る。
でも「debug setting」とか怪しいのでお勧めしない。