Utilizzo di setDate in PreparedStatement

Per rendere il nostro codice più standard, ci è stato chiesto di modificare tutti i punti in cui sono state codificate le nostre variabili SQL in istruzioni preparate e di associare invece le variabili.

Sto comunque affrontando un problema con il setDate() .

Ecco il codice:

  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)); 

Ottengo questo errore quando l’SQL viene eseguito:

  java.lang.IllegalArgumentException at java.sql.Date.valueOf(Date.java:138) at com.cmsi.eValuate.TAF.TAFModuleMain.CallTAF(TAFModuleMain.java:1211) 

Dovrei usare setString() invece con un to_date() ?

    ❐ Utilizzo di java.sql.Date

    Se la tua tabella ha una colonna di tipo DATE :

    • java.lang.String

      Il metodo java.sql.Date.valueOf(java.lang.String) ricevuto una stringa che rappresenta una data nel formato yyyy-[m]m-[d]d . per esempio:

       ps.setDate(2, java.sql.Date.valueOf("2013-09-04")); 
    • java.util.Date

      Supponete di avere una variabile endDate di tipo java.util.Date , quindi effettuate la conversione:

       ps.setDate(2, new java.sql.Date(endDate.getTime()); 
    • attuale

      Se si desidera inserire la data corrente:

       ps.setDate(2, new java.sql.Date(System.currentTimeMillis())); // Since Java 8 ps.setDate(2, java.sql.Date.valueOf(java.time.LocalDate.now())); 

    ❐ Uso di java.sql.Timestamp

    Se la tua tabella ha una colonna di tipo TIMESTAMP o DATETIME :

    • java.lang.String

      Il metodo java.sql.Timestamp.valueOf(java.lang.String) ricevuto una stringa che rappresenta una data nel formato yyyy-[m]m-[d]d hh:mm:ss[.f...] . per esempio:

       ps.setTimestamp(2, java.sql.Timestamp.valueOf("2013-09-04 13:30:00"); 
    • java.util.Date

      Supponete di avere una variabile endDate di tipo java.util.Date , quindi effettuate la conversione:

       ps.setTimestamp(2, new java.sql.Timestamp(endDate.getTime())); 
    • attuale

      Se si richiede il timestamp corrente:

       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())); 

    tl; dr

    Con JDBC 4.2 o successivo e java 8 o successivo:

     myPreparedStatement.setObject( … , myLocalDate ) 

    …e…

     myResultSet.getObject( … , LocalDate.class ) 

    Dettagli

    La risposta di Vargas fa bene a menzionare i tipi java.time ma si riferisce solo alla conversione in java.sql.Date. Non c’è bisogno di convertire se il tuo driver è aggiornato.

    java.time

    Il framework java.time è integrato in Java 8 e versioni successive. Queste classi sostituiscono le vecchie e fastidiose classi data-ora come java.util.Date , .Calendar e java.text.SimpleDateFormat . Il team Joda-Time consiglia anche la migrazione a java.time.

    Per saperne di più, consultare l’ esercitazione Oracle . E cerca Stack Overflow per molti esempi e spiegazioni.

    Gran parte della funzionalità java.time è backportata su Java 6 e 7 in ThreeTen-Backport e ulteriormente adattata ad Android in ThreeTenABP .

    LocalDate

    In java.time, la class java.time.LocalDate rappresenta un valore di sola data senza ora del giorno e senza fuso orario.

    Se si utilizza un driver JDBC conforms alle specifiche JDBC 4.2 o successive, non è necessario utilizzare la vecchia class java.sql.Date . È ansible passare / recuperare oggetti LocalDate direttamente al / dal proprio database tramite PreparedStatement::setObject e ResultSet::getObject .

     LocalDate localDate = LocalDate.now( ZoneId.of( "America/Montreal" ) ); myPreparedStatement.setObject( 1 , localDate ); 

    …e…

     LocalDate localDate = myResultSet.getObject( 1 , LocalDate.class ); 

    Prima di JDBC 4.2, convertire

    Se il tuo driver non può gestire direttamente i tipi java.time, torna alla conversione in tipi java.sql. Ma minimizza il loro uso, con la tua logica aziendale usando solo i tipi java.time.

    Nuovi metodi sono stati aggiunti alle vecchie classi per la conversione da / verso i tipi java.time. Per java.sql.Date vedere i metodi valueOf e toLocalDate .

     java.sql.Date sqlDate = java.sql.Date.valueOf( localDate ); 

    …e…

     LocalDate localDate = sqlDate.toLocalDate(); 

    Valore segnaposto

    Fai attenzione a utilizzare il valore di segnaposto come mostrato nel codice della tua domanda. Non tutti i database e altri software possono gestire indietro nel tempo. Suggerisco di usare qualcosa come la data di riferimento dell’epoca Unix / Posix comunemente usata nel 1970, 1970-01-01 .

     LocalDate EPOCH_DATE = LocalDate.ofEpochDay( 0 ); // 1970-01-01 is day 0 in Epoch counting. 

    A proposito di java.time

    Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantano le fastidiose vecchie lezioni di data e ora come java.util.Date , Calendar e SimpleDateFormat .

    Il progetto Joda-Time , ora in modalità di manutenzione , consiglia la migrazione alle classi java.time .

    Per saperne di più, consultare l’ esercitazione Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

    È ansible scambiare oggetti java.time direttamente con il proprio database. Utilizzare un driver JDBC compatibile con JDBC 4.2 o successivo. Nessuna necessità di stringhe, nessuna necessità per le classi java.sql.* .

    Dove ottenere le classi java.time?

    • Java SE 8 , Java SE 9 , Java SE 10 e versioni successive
      • Built-in.
      • Parte dell’API Java standard con un’implementazione in bundle.
      • Java 9 aggiunge alcune funzionalità e correzioni minori.
    • Java SE 6 e Java SE 7
      • Gran parte della funzionalità java.time è back-porting su Java 6 e 7 in ThreeTen-Backport .
    • android
      • Versioni successive di implementazioni di bundle Android delle classi java.time.
      • Per Android precedente (<26), il progetto ThreeTenABP adatta ThreeTen-Backport (menzionato sopra). Vedi Come usare ThreeTenABP ….

    Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un terreno di prova per possibili aggiunte future a java.time. Puoi trovare alcune classi utili come Interval , YearWeek , YearQuarter e altro .

    Il problema che stai avendo è che stai trasmettendo formati incompatibili da un java.util.Date formattato per build un’istanza di java.sql.Date , che non si comporta allo stesso modo quando si usa valueOf() dal momento che usano diversi formati.

    Vedo anche che il tuo objective è mantenere ore e minuti, e penso che è meglio cambiare il tipo di dati in java.sql.Timestamp , che supporta ore e minuti, insieme a modificare il campo del database in DATETIME o simile (a seconda del fornitore del database).

    Ad ogni modo, se si desidera passare da java.util.Date to java.sql.Date , suggerisco di utilizzare

     java.util.Date date = Calendar.getInstance().getTime(); java.sql.Date sqlDate = new java.sql.Date(date.getTime()); // ... more code here prs.setDate(sqlDate); 

    I documenti affermano esplicitamente che java.sql.Date genererà:

    • IllegalArgumentException – se la data indicata non è nel formato di escape della data JDBC ( yyyy-[m]m-[d]d )

    Inoltre non dovrebbe essere necessario convertire una data in una String quindi in un file sql.date , questo sembra superfluo (e sobject a bug!). Invece potresti:

     java.sql.Date sqlDate := new java.sql.Date(now.getTime()); prs.setDate(2, sqlDate); prs.setDate(3, sqlDate); 

    Se si desidera aggiungere la data corrente nel database, evitare di calcolare la data in Java per iniziare. Determinare “ora” sul lato Java (client) porta a possibili incoerenze nel database se il lato client è configurato in modo errato, ha il tempo sbagliato, il fuso orario sbagliato, ecc. Invece, la data può essere impostata sul lato server in un modo come il seguente:

     requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER (" + "REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " + "VALUES(?, SYSDATE, SYSDATE + 30)"; ... prs.setInt(1, new Integer(requestID)); 

    In questo modo, è richiesto un solo parametro di collegamento e le date calcolate sul lato server saranno coerenti. Ancora meglio sarebbe aggiungere un trigger di inserimento a CREDIT_REQ_TITLE_ORDER e inserire il trigger nelle date. Ciò può aiutare a rafforzare la coerenza tra le diverse app client (ad esempio, qualcuno che tenta di eseguire una correzione tramite sqlplus.

    Non sono sicuro, ma quello che penso tu stia cercando è di creare un java.util.Date da una stringa, quindi convertire quel java.util.Date in un java.sql.Date.

    prova questo:

     private static java.sql.Date getCurrentDate(String date) { java.util.Date today; java.sql.Date rv = null; try { SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy"); today = format.parse(date); rv = new java.sql.Date(today.getTime()); System.out.println(rv.getTime()); } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); } finally { return rv; } } 

    Restituisce un object java.sql.Date per setDate ();

    La funzione sopra riportata stamperà un valore lungo:

    1375934400000