web-dev-qa-db-ja.com

Java 8?

Java 8 + JDBCの専門家は、次の推論に問題があるかどうかを教えてもらえますか?そして、神の秘密にある場合、なぜこれが行われなかったのですか?

_Java.sql.Date_は現在、JDBCがDATE SQL型にマップするために使用する型であり、時間とタイムゾーンのない日付を表します。しかし、このクラスは実際には_Java.util.Date_のサブクラスであり、ミリ秒までの正確な瞬間を保存するため、ひどく設計されています。

データベースの日付2015-09-13を表すために、タイムゾーンを選択し、そのタイムゾーンの文字列「2015-09-13T00:00:00.000」をJava.util.Dateとして解析してミリ秒を取得する必要があります。値、次にこのミリ秒値から_Java.sql.Date_を構築し、最後に準備されたステートメントでsetDate()を呼び出し、JDBCドライバーが正しく再計算できるように選択されたタイムゾーンを保持するカレンダーを渡しますこのミリ秒の値から2015-09-13の日付。このプロセスは、どこでもデフォルトのタイムゾーンを使用し、カレンダーを渡さないことにより、少し簡単になります。

Java 8はLocalDateクラスを導入します。これは、正確な瞬間ではなく、したがってタイムゾーンに依存しないため、DATEデータベースタイプにより適しています。また、Java 8では、PreparedStatementおよびResultSetインターフェースに下位互換性のある変更を加えることができるデフォルトのメソッドも導入されています。

したがって、下位互換性を維持しながら、JDBCの混乱を一掃する大きな機会を逃していませんか? Java 8は、単にPreparedStatementおよびResultSetにこれらのデフォルトメソッドを追加することができます。

_default public void setLocalDate(int parameterIndex, LocalDate localDate) {
    if (localDate == null) {
        setDate(parameterIndex, null);
    }
    else {
        ZoneId utc = ZoneId.of("UTC");
        Java.util.Date utilDate = Java.util.Date.from(localDate.atStartOfDay(utc).toInstant());
        Date sqlDate = new Date(utilDate.getTime());
        setDate(parameterIndex, sqlDate, Calendar.getInstance(TimeZone.getTimeZone(utc)));
    }
}

default LocalDate getLocalDate(int parameterIndex) {
    ZoneId utc = ZoneId.of("UTC");
    Date sqlDate = getDate(parameterIndex, Calendar.getInstance(TimeZone.getTimeZone(utc)));
    if (sqlDate == null) {
        return null;
    }

    Java.util.Date utilDate = new Java.util.Date(sqlDate.getTime());
    return utilDate.toInstant().atZone(utc).toLocalDate();
}
_

もちろん、TIMESTAMP型のInstantのサポート、およびTIME型のLocalTimeのサポートにも同じ理由が当てはまります。

38
JB Nizet

データベースの日付2015-09-13を表すために、タイムゾーンを選択し、そのタイムゾーンの文字列「2015-09-13T00:00:00.000」をJava.util.Dateとして解析してミリ秒を取得する必要があります。値、このミリ秒値からJava.sql.Dateを構築し、最後に準備されたステートメントでsetDate()を呼び出し、JDBCドライバーが日付を正しく再計算できるように選択されたタイムゾーンを保持するカレンダーを渡します2015-09このミリ秒値から-13

どうして?電話するだけ

_Date.valueOf("2015-09-13"); // From String
Date.valueOf(localDate);    // From Java.time.LocalDate
_

動作は、すべてのJDBCドライバーで正しいものになります。タイムゾーンのないローカル日付。逆の操作は次のとおりです。

_date.toString();    // To String
date.toLocalDate(); // To Java.time.LocalDate
_

_Java.sql.Date__Java.util.Date_ への依存関係、および _Java.time.Instant_Date(long) または Date.getTime() 経由

後方互換性を維持しながら、JDBCの混乱を一掃する大きな機会を逃していませんか? [...]

場合によります。 JDBC 4.2仕様 は、 setObject(int, localDate) を介してLocalDateタイプをバインドし、LocalDategetObject(int, LocalDate.class) で入力します(ドライバーが準備ができている場合)。もちろん、あなたが提案したような、より正式なdefaultメソッドほどエレガントではありません。

29
Lukas Eder