Java.util.Date
vs Java.sql.Date
:いつ使うのか、そしてその理由は?
おめでとうございます、JDBC:Dateクラスの処理が大好きです。
基本的にデータベースは通常少なくともthree形式のdatetimeフィールドをサポートします。これはdate、timeそしてtimestampです。これらはそれぞれJDBCに対応するクラスを持ち、それぞれが Java.util.Date
を拡張します。これら3つのそれぞれのクイックセマンティクスは次のとおりです。
Java.sql.Date
はSQL DATEに対応します。つまり、年、月、日を格納し、時、分、秒、ミリ秒は無視されます。さらにsql.Date
はタイムゾーンに関連付けられていません。Java.sql.Time
はSQL TIMEに対応し、明らかなように時、分、秒、ミリ秒についての情報のみを含みます。Java.sql.Timestamp
は、カスタマイズ可能な精度でナノ秒(util.Date
はミリ秒だけをサポートします!)までの正確な日付であるSQL TIMESTAMPに対応します。これら3つの型に関してJDBCドライバを使用するときの最も一般的なバグの1つは、型が誤って処理されることです。これは、sql.Date
はタイムゾーン固有であり、sql.Time
は現在の年、月、日などを含むことを意味します。
実際には、フィールドのSQL型に依存します。 PreparedStatement
には3つの値すべての設定子があり、#setDate()
はsql.Date
、#setTime()
はsql.Time
、#setTimestamp()
はsql.Timestamp
です。
ps.setObject(fieldIndex, utilDateObject);
を使用する場合、ほとんどのJDBCドライバに通常のutil.Date
を渡すことができますが、それは正しい型であるかのように喜んでそれを食い物にしますが、後でデータを要求するとき、実際にものが足りないことに気付くでしょう。
私が言っていることは、ミリ秒/ナノ秒を普通の長さとして保存し、それらをあなたが使用しているどんなオブジェクトにも変換することです(obligatory joda-time plug)。 1つの手っ取り早い方法は、日付コンポーネントを別の日付コンポーネントとして保存することです。例えば、今は20100221と154536123です。これらのマジックナンバーはSQLクエリで使用でき、データベース間で移植できます。 JDBC/Java Date APIのこの部分を完全に避けることができます。
最後の編集: Java 8以降は、Java.util.Date
もJava.sql.Date
も使用できない場合は使用しないでください。代わりに(Jodaベースの) Java.time
パッケージを使用することをお勧めします。 Java 8を使用していない場合は、これが元の応答です。
Java.sql.Date
- それを使用するライブラリのメソッド/コンストラクタを呼び出すとき(JDBCのように)。他にはありません。 JDBCを明示的に扱わないアプリケーション/モジュールのデータベースライブラリに依存関係を導入したくはありません。
Java.util.Date
- それを使うライブラリを使うとき。それ以外の場合、いくつかの理由から、可能な限り少なくします。
これは変更可能です。つまり、メソッドに渡すたびに、またはメソッドから戻すたびに、防御コピーを作成する必要があります。
それは日付をあまりうまく処理しません、それはあなたのもののような人々を本当に逆にします、日付処理クラスがすべきだと思います。
さて、j.u.Dはうまく機能しないので、Calendar
クラスが導入されました。それらはまた変更可能で、一緒に使うのがひどいので、あなたに選択の余地がなければ避けるべきです。
Joda Time API (のようなより良い選択肢があります。これはJava 7にもなり、新しい公式の日付処理APIになるかもしれません。 - クイック検索 はそうではないと言います)。
Jodaのような新しい依存関係を導入するのがやり過ぎだと感じた場合、オブジェクトのタイムスタンプフィールドにlong
sを使用するのはそれほど悪いことではありません。
Java.sql.Date
を使うのはPreparedStatement.setDate
の中だけです。それ以外の場合は、Java.util.Date
を使用してください。 ResultSet.getDate
はJava.sql.Date
を返すと言っていますが、Java.util.Date
に直接代入することができます。
私は同じ問題を抱えていました、準備されたステートメントに現在の日付を挿入するために私が見つけた最も簡単な方法はこれです:
preparedStatement.setDate(1, new Java.sql.Date(new Java.util.Date().getTime()));
JavaのJava.util.Dateクラスは特定の瞬間を表します(例:2013年11月25日16時30分45秒からミリ秒まで)。ただし、DBのDATEデータ型は日付のみを表します(例: 2013年11月25日)。誤ってJava.util.DateオブジェクトをDBに提供しないようにするために、JavaではSQLパラメータを直接Java.util.Dateに設定することはできません。
PreparedStatement st = ...
Java.util.Date d = ...
st.setDate(1, d); //will not work
しかしそれでも、あなたはそれを力/意図によって行うことができます(そして時間と分はDBドライバーによって無視されます)。これはJava.sql.Dateクラスで行われます。
PreparedStatement st = ...
Java.util.Date d = ...
st.setDate(1, new Java.sql.Date(d.getTime())); //will work
Java.sql.Dateオブジェクトは、(Java.util.Dateから構築するのが簡単になるように)瞬間を格納することができますが、時間を要求しようとすると例外をスローします(その概念を強制するため)。日付のみ)。 DBドライバはこのクラスを認識し、時間に0を使用することが期待されています。これを試して:
public static void main(String[] args) {
Java.util.Date d1 = new Java.util.Date(12345);//ms since 1970 Jan 1 midnight
Java.sql.Date d2 = new Java.sql.Date(12345);
System.out.println(d1.getHours());
System.out.println(d2.getHours());
}