JDBCを使用してOracle DBテーブルからDATETIME列を取得したいと思います。ここに私のコードがあります:
int columnType = rsmd.getColumnType(i);
if(columnType == Types.DATE)
{
Date aDate = rs.getDate(i);
valueToInsert = aDate.toString();
}
else if(columnType == Types.TIMESTAMP)
{
Timestamp aTimeStamp = rs.getTimestamp(i);
valueToInsert = aTimeStamp.toString();
}
else
{
valueToInsert = rs.getString(i);
}
最初に列タイプを識別する必要があります。興味のあるフィールドは、Types.DATEとして認識されますが、この形式は「07.05.2009 13:49:32」であるため、DBでは実際にはDATETIMEです。
getDateは時刻を切り捨てます: "07.05.2009"およびgetStringは ".0"を追加します: "07.05.2009 13:49:32.0"
もちろん、最後の.0を削除して常にgetStringを操作することもできますが、これは汚い回避策です。
何か案は ? getDateTimeメソッドを探していました。
乾杯、ティム
Java.util.Date date;
Timestamp timestamp = resultSet.getTimestamp(i);
if (timestamp != null)
date = new Java.util.Date(timestamp.getTime()));
次に、好きなようにフォーマットします。
Leos Literakによる回答 は正しいですが、今では時代遅れで、面倒な古い日時クラスの1つであるJava.sql.Timestamp
を使用しています。
それは本当にDBのDATETIMEです
いいえ、そうではありません。 OracleデータベースにはDATETIME
などのデータ型はありません。
GetDateTimeメソッドを探していました。
質問に見られる面倒なレガシークラスではなく、JDBC 4.2以降のJava.timeクラスを使用します。特に、Java.sql.TIMESTAMP
ではなく、SQL標準型TIMESTAMP WITH TIME ZONE
などのちょっとしたInstant
クラスを使用します。
工夫されたコードスニペット:
if(
JDBCType.valueOf(
myResultSetMetaData.getColumnType( … )
)
.equals( JDBCType.TIMESTAMP_WITH_TIMEZONE )
) {
Instant instant = myResultSet.getObject( … , Instant.class ) ;
}
JDBCを使用してOracle DBテーブルからDATETIME列を取得したいと思います。
this doc によると、Oracleデータベースには列データ型DATETIME
がありません。その用語は、すべての日時タイプをグループとして参照するOracleの単語のようです。
型を検出し、どのデータ型で分岐するかというコードのポイントはわかりません。一般に、特定のテーブルと特定のビジネス上の問題のコンテキストでコードを明示的に作成する必要があると思います。おそらく、これは何らかの汎用フレームワークで役立つでしょう。主張する場合は、さまざまなタイプについて学び、Java 8以降に組み込まれている非常に有用な新しいJava.timeクラスについて学習してください。質問で使用されるクラス。
valueToInsert = aDate.toString();
String
オブジェクトとして、データベースとテキストで日時値を交換しようとしているようです。しないでください。
データベースと日時値を交換するには、日時オブジェクトを使用します。 Java 8以降では、以下に説明するように、Java.timeオブジェクトを意味します。
日付と時刻に関連する3種類のデータタイプを混同している可能性があります。
SQL標準 5つのタイプを定義します :
DATE
TIME WITHOUT TIME ZONE
TIME WITH TIME ZONE
TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP WITH TIME ZONE
DATE
TIME
またはTIME WITHOUT TIME ZONE
TIME WITH TIME ZONE
(またはTIMETZ
)TIMESTAMP
またはTIMESTAMP WITHOUT TIME ZONE
TIMESTAMP WITH TIME ZONE
(またはTIMESTAMPTZ
)多くのデータベースは、独自の日時関連タイプを提供します。独自のタイプは、widelyによって異なります。いくつかは避けるべき古い古いタイプです。一部のベンダーは、特定の利点を提供すると信じています。標準タイプのみを使用するかどうかを決定します。注意:一部の独自型には、標準型と競合する名前があります。私はあなたを見ています Oracle DATE
。
Javaプラットフォームは、SQL標準データベースまたは特定のデータベースとは異なる方法で日時の内部詳細を処理します。 JDBCドライバー の仕事は、これらの違いを仲介し、橋として機能し、必要に応じて型と実際に実装されたデータ値を変換することです。 Java.sql。*パッケージ はそのブリッジです。
Java 8より前は、 JDBC 仕様が日時作業用に3つのタイプを定義していました。最初の2つは、バージョン8以前のようにハッキングです。Javaには、日付のみまたは時間のみの値を表すクラスがありませんでした。
したがって、 ResultSet interface には「getDateTime」メソッドがないという質問に答えます。このインターフェイスは、JDBCで定義されている3つのブリッジングデータタイプに対して getterメソッド を提供します。
getDate
Java.sql.Dateの場合getTime
Java.sql.Timeの場合getTimestamp
Java.sql.Timestampの場合最初のものには、タイムゾーンまたはUTCからのオフセットの概念がないことに注意してください。最後のJava.sql.Timestamp
は、そのtoString
メソッドが示していることにもかかわらず、常にUTCです。
上記の設計が不十分なJDBCクラスは避けてください。それらはJava.timeタイプに取って代わられます。
Java.sql.Date
の代わりに、LocalDate
を使用します。 SQL標準のDATE
タイプに適合します。Java.sql.Time
の代わりに、LocalTime
を使用します。 SQL標準のTIME WITHOUT TIME ZONE
型に適合します。Java.sql.Timestamp
の代わりに、Instant
を使用します。 SQL標準のTIMESTAMP WITH TIME ZONE
型に適合します。JDBC 4.2以降では、Java.timeオブジェクトをデータベースと直接交換できます。 setObject
/getObject
メソッドを使用します。
挿入/更新。
myPreparedStatement.setObject( … , instant ) ;
検索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Instant
クラスは、 UTC のタイムライン上の瞬間を ナノ秒 (小数部の最大9桁)の解像度で表します。
UTCとしてではなく、特定の地域(タイムゾーン)の人々が使用する壁時計時間で見たInstant
の瞬間を確認したい場合は、ZoneId
を適用してZonedDateTime
オブジェクトを取得して調整します。
ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdtAuckland = instant.atZone( zAuckland ) ;
結果のZonedDateTime
オブジェクトは同じ瞬間、タイムライン上の同じ同時ポイントです。新しい日は東の方が早いため、日付と時刻は異なります。たとえば、ニュージーランドの真夜中から数分後は、UTCでは「昨日」のままです。
Instant
またはZonedDateTime
のいずれかにさらに別のタイムゾーンを適用して、他の地域の人々が使用するさらに別の壁時計時刻を介して同じ瞬間を見ることができます。
ZoneId zMontréal = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdtMontréal = zdtAuckland.withZoneSameInstant( zMontréal ) ; // Or, for the same effect: instant.atZone( zMontréal )
したがって、3つのオブジェクト(instant
、zdtAuckland
、zMontréal
)があり、すべてが同じ瞬間、タイムライン上の同じポイントを表します。
データベースのデータ型の検出に関する質問のコードに戻るには、(a)私の専門分野ではなく、(b)上で述べたようにこれを避けます。(c)これを主張する場合は、注意してくださいJava 8以降では、Java.sql.Types
クラスは旧式です。そのクラスは、新しいインターフェイスを実装する Enum
の適切な Java JDBCType
に置き換えられました SQLType
。関連する質問の この回答 を参照してください。
この変更は、 JDBC Maintenance Release 4.2 、セクション3および4にリストされています。
Java.sql.JDBCType列挙型の追加
JDBCタイプと呼ばれる汎用SQLタイプを識別するために使用されるEnum。その目的は、Types.Javaで定義されている定数の代わりにJDBCTypeを使用することです。
列挙型は古いクラスと同じ値を持ちますが、 type-safety を提供します。
構文に関する注意:最新のJavaでは、switch
オブジェクトでEnum
を使用できます。したがって、質問にあるように、カスケードif-thenステートメントを使用する必要はありません。難点の1つは、なんらかの技術的な理由で切り替える場合、enumオブジェクトの名前を非修飾で使用する必要があるため、修飾されたTIMESTAMP_WITH_TIMEZONE
ではなくJDBCType.TIMESTAMP_WITH_TIMEZONE
でswitch
を実行する必要があることです。 static import
ステートメントを使用します。
そのため、次のコード例のようなことができると思います(まだ試していません)。
final int columnType = myResultSetMetaData.getColumnType( … ) ;
final JDBCType jdbcType = JDBCType.valueOf( columnType ) ;
switch( jdbcType ) {
case DATE : // FYI: Qualified type name `JDBCType.DATE` not allowed in a switch, because of an obscure technical issue. Use a `static import` statement.
…
break ;
case TIMESTAMP_WITH_TIMEZONE :
…
break ;
default :
…
break ;
}
Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、 Java.util.Date
、 Calendar
、& SimpleDateFormat
などの厄介な古い legacy date-timeクラスに取って代わります。
Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.time クラスへの移行を推奨しています。
詳細については、 Oracle Tutorial を参照してください。また、Stack Overflowで多くの例と説明を検索してください。仕様は JSR 31 です。
Java.timeオブジェクトをデータベースと直接交換できます。 JDBC 4.2 以降に準拠する JDBCドライバー を使用します。文字列もJava.sql.*
クラスも必要ありません。
Java.timeクラスはどこで入手できますか?
ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある証明の場です。 Interval
、 YearWeek
、 YearQuarter
、 more などの便利なクラスがあります。
PDATE:Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.time への移行を推奨していますクラス。このセクションは履歴としてそのまま残りました。
Java 8(Java.time。*パッケージ)より前は、Java(Java.util.Date&Calendar、Java.text.SimpleDateFormat)にバンドルされている日時クラスは、面倒で混乱しやすいため、欠陥がある。
より良い方法は、JDBCドライバーが提供するものを使用して、Joda-Timeオブジェクトを作成するか、Java 8 Java.time。* package で作成することです。最終的に、新しいJava.time。*クラスを自動的に使用する新しいJDBCドライバーが表示されるはずです。それまで、Java.sql.Timestampなどのクラスに、 toInstant
やfromInstant
などのJava.timeを挿入するためのメソッドがいくつか追加されました。
質問の後半については、文字列のレンダリング…フォーマッタオブジェクトを使用して文字列値を生成する必要があります。
昔ながらの方法は、Java.text.SimpleDateFormatを使用することです。推奨されません。
Joda-Timeはさまざまな組み込みフォーマッタを提供しますが、独自のフォーマッタを定義することもできます。しかし、あなたが述べたようにログやレポートを書く場合、最良の選択はISO 8601形式かもしれません。その形式は、たまたま Joda-Time とJava.timeによって使用されるデフォルトです。
//Java.sql.Timestamp timestamp = resultSet.getTimestamp(i);
// Or, fake it
// long m = DateTime.now().getMillis();
// Java.sql.Timestamp timestamp = new Java.sql.Timestamp( m );
//DateTime dateTimeUtc = new DateTime( timestamp.getTime(), DateTimeZone.UTC );
DateTime dateTimeUtc = new DateTime( DateTimeZone.UTC ); // Defaults to now, this moment.
// Convert as needed for presentation to user in local time zone.
DateTimeZone timeZone = DateTimeZone.forID("Europe/Paris");
DateTime dateTimeZoned = dateTimeUtc.toDateTime( timeZone );
コンソールにダンプ…
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeZoned: " + dateTimeZoned );
実行すると…
dateTimeUtc: 2014-01-16T22:48:46.840Z
dateTimeZoned: 2014-01-16T23:48:46.840+01:00
これは働いた:
Date date = null;
String dateStr = rs.getString("doc_date");
if (dateStr != null) {
date = dateFormat.parse(dateStr);
}
simpleDateFormatを使用します。
私が選んだ解決策は、mysqlクエリで日付をフォーマットすることでした:
String l_mysqlQuery = "SELECT DATE_FORMAT(time, '%Y-%m-%d %H:%i:%s') FROM uld_departure;"
l_importedTable = fStatement.executeQuery( l_mysqlQuery );
System.out.println(l_importedTable.getString( timeIndex));
私はまったく同じ問題を抱えていました。 mysqlテーブルには次のような形式の日付が含まれていますが:2017-01-01 21:02:50
String l_mysqlQuery = "SELECT time FROM uld_departure;"
l_importedTable = fStatement.executeQuery( l_mysqlQuery );
System.out.println(l_importedTable.getString( timeIndex));
そのようにフォーマットされた日付を返していました:2017-01-01 21:02:50.0