コードをより標準にするために、SQL変数をハードコーディングしたすべての場所を準備済みステートメントに変更し、代わりに変数をバインドするように求められました。
しかし、setDate()
で問題に直面しています。
コードは次のとおりです。
DateFormat dateFormatYMD = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
DateFormat dateFormatMDY = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date now = new Date();
String vDateYMD = dateFormatYMD.format(now);
String vDateMDY = dateFormatMDY.format(now);
String vDateMDYSQL = vDateMDY ;
Java.sql.Date date = new Java.sql.Date(0000-00-00);
requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER (REQUEST_ID," +
" ORDER_DT, FOLLOWUP_DT) " + "values(?,?,?,)";
prs = conn.prepareStatement(requestSQL);
prs.setInt(1,new Integer(requestID));
prs.setDate(2,date.valueOf(vDateMDYSQL));
prs.setDate(3,date.valueOf(sqlFollowupDT));
SQLが実行されると、次のエラーが表示されます。
Java.lang.IllegalArgumentException
at Java.sql.Date.valueOf(Date.Java:138)
at com.cmsi.eValuate.TAF.TAFModuleMain.CallTAF(TAFModuleMain.Java:1211)
setString()
の代わりにto_date()
を使用する必要がありますか?
Java.sql.Date
の使用テーブルにDATE
型の列がある場合:
Java.lang.String
メソッド Java.sql.Date.valueOf(Java.lang.String)
は、yyyy-[m]m-[d]d
形式の日付を表す文字列を受け取りました。例えば。:
ps.setDate(2, Java.sql.Date.valueOf("2013-09-04"));
Java.util.Date
タイプJava.util.Date
の変数endDate
があるとします。こうして変換を行います。
ps.setDate(2, new Java.sql.Date(endDate.getTime());
現在
現在の日付を挿入する場合:
ps.setDate(2, new Java.sql.Date(System.currentTimeMillis()));
// Since Java 8
ps.setDate(2, Java.sql.Date.valueOf(Java.time.LocalDate.now()));
Java.sql.Timestamp
の使用テーブルにTIMESTAMP
またはDATETIME
タイプの列がある場合:
Java.lang.String
メソッド Java.sql.Timestamp.valueOf(Java.lang.String)
は、yyyy-[m]m-[d]d hh:mm:ss[.f...]
形式の日付を表す文字列を受け取りました。例えば。:
ps.setTimestamp(2, Java.sql.Timestamp.valueOf("2013-09-04 13:30:00");
Java.util.Date
タイプJava.util.Date
の変数endDate
があるとします。こうして変換を行います。
ps.setTimestamp(2, new Java.sql.Timestamp(endDate.getTime()));
現在
現在のタイムスタンプが必要な場合:
ps.setTimestamp(2, new Java.sql.Timestamp(System.currentTimeMillis()));
// Since Java 8
ps.setTimestamp(2, Java.sql.Timestamp.from(Java.time.Instant.now()));
ps.setTimestamp(2, Java.sql.Timestamp.valueOf(Java.time.LocalDateTime.now()));
JDBC 4.2以降およびJava 8以降の場合:
myPreparedStatement.setObject( … , myLocalDate )
…そして…
myResultSet.getObject( … , LocalDate.class )
VargasのAnswerは、Java.time型について言及するのに適していますが、Java.sql.Dateへの変換のみを参照しています。ドライバーが更新された場合、変換する必要はありません。
Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、Java.util.Date
、.Calendar
、Java.text.SimpleDateFormat
などの古い面倒な日時クラスに取って代わります。 Joda-Time チームは、Java.timeへの移行も推奨しています。
詳細については、 Oracleチュートリアル を参照してください。また、多くの例と説明についてはStack Overflowを検索してください。
Java.time機能の多くは、 ThreeTen-Backport でJava 6および7にバックポートされ、さらに ThreeTenABP でAndroidに適合します。
LocalDate
Java.timeでは、 Java.time.LocalDate
クラスは、時刻およびタイムゾーンのない日付のみの値を表します。
JDBC 4.2 以降の仕様に準拠する JDBCドライバー を使用する場合、古い Java.sql.Date
クラスを使用する必要はありません。 PreparedStatement::setObject
および ResultSet::getObject
を使用して、LocalDate
オブジェクトをデータベースと直接やり取りできます。
LocalDate localDate = LocalDate.now( ZoneId.of( "America/Montreal" ) );
myPreparedStatement.setObject( 1 , localDate );
…そして…
LocalDate localDate = myResultSet.getObject( 1 , LocalDate.class );
ドライバーがJava.time型を直接処理できない場合は、Java.sql型への変換にフォールバックします。ただし、Java.time型のみを使用するビジネスロジックで、それらの使用を最小限に抑えてください。
Java.time型との間の変換のために、新しいメソッドが古いクラスに追加されました。 Java.sql.Date
については、 valueOf
および toLocalDate
メソッドを参照してください。
Java.sql.Date sqlDate = Java.sql.Date.valueOf( localDate );
…そして…
LocalDate localDate = sqlDate.toLocalDate();
質問のコードに示されているように、0000-00-00
をプレースホルダー値として使用する場合は注意してください。すべてのデータベースや他のソフトウェアが、その時点までさかのぼることができるわけではありません。よく使用される nix/Posix Epochの基準日 1970年の1970-01-01
のようなものを使用することをお勧めします。
LocalDate Epoch_DATE = LocalDate.ofEpochDay( 0 ); // 1970-01-01 is day 0 in Epoch counting.
Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、 Java.util.Date
、 Calendar
、および SimpleDateFormat
などの厄介な古い レガシー 日時クラスに取って代わります。
メンテナンスモード になった 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 。
あなたが持っている問題は、フォーマットされたJava.util.Dateから互換性のないフォーマットを渡してJava.sql.Date
のインスタンスを構築していることです。これはvalueOf()
を使用するときと同じようには動作しません異なる形式を使用します。
また、時間と分を維持することを目指していることもわかります。データ型をJava.sql.Timestamp
に変更することをお勧めします。これは、データベースフィールドをDATETIMEなどに変更するとともに、時間と分をサポートします。 (データベースベンダーによって異なります)。
とにかく、Java.util.Date to Java.sql.Date
から変更する場合は、使用することをお勧めします
Java.util.Date date = Calendar.getInstance().getTime();
Java.sql.Date sqlDate = new Java.sql.Date(date.getTime());
// ... more code here
prs.setDate(sqlDate);
docs は、Java.sql.Date
がスローすることを明示的に示しています。
IllegalArgumentException
-指定された日付がJDBC日付エスケープ形式でない場合(yyyy-[m]m-[d]d
)
また、日付をString
に変換してからsql.date
に変換する必要はないはずです。これは不要なようです(バグが発生しやすい!)。代わりに次のことができます。
Java.sql.Date sqlDate := new Java.sql.Date(now.getTime());
prs.setDate(2, sqlDate);
prs.setDate(3, sqlDate);
現在の日付をデータベースに追加する場合は、Javaで日付を計算することを避けます。 Java(クライアント)側で「今」を決定すると、クライアント側の設定が間違っていたり、時刻やタイムゾーンが間違っていたりすると、データベースで矛盾が発生する可能性があります。代わりに、日付を設定できますサーバー側で次のような方法で:
requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER (" +
"REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " +
"VALUES(?, SYSDATE, SYSDATE + 30)";
...
prs.setInt(1, new Integer(requestID));
この方法では、1つのバインドパラメーターのみが必要であり、サーバー側で日付が計算されるのは一貫しています。さらに良いのは、CREDIT_REQ_TITLE_ORDER
に挿入トリガーを追加し、トリガーに日付を挿入させることです。これにより、さまざまなクライアントアプリ(たとえば、sqlplusを介して修正を試みる人)間の一貫性を強化できます。