Używanie setDate w PreparedStatement

Aby uczynić nasz kod bardziej standardowym, zostaliśmy poproszeni o zmianę wszystkich miejsc, w których zakodowaliśmy na twardo nasze zmienne SQL, na przygotowane instrukcje i zamiast tego powiązaliśmy zmienne.

Mam jednak problem z setDate().

Oto kod:

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

Dostaję ten błąd podczas wykonywania SQL:

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

Czy powinienem używać setString() zamiast to_date()?

Author: Kevin Panko, 2013-09-04

6 answers

❐ Using java.sql.Date

Jeśli twoja tabela ma kolumnę typu DATE:

  • java.lang.String

    Metoda java.sql.Date.valueOf(java.lang.String) otrzymano ciąg znaków reprezentujący datę w formacie yyyy-[m]m-[d]d. np.:

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

    Załóżmy, że masz zmienną endDate typu java.util.Date, dokonujesz konwersji w ten sposób:

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

    Jeśli chcesz wstawić bieżący Data:

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

❐ Using java.sql.Timestamp

Jeśli twoja tabela ma kolumnę typu TIMESTAMP lub DATETIME:

  • java.lang.String

    Metoda java.sql.Timestamp.valueOf(java.lang.String) otrzymano ciąg znaków reprezentujący datę w formacie yyyy-[m]m-[d]d hh:mm:ss[.f...]. np.:

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

    Załóżmy, że masz zmienną endDate typu java.util.Date, dokonujesz konwersji w ten sposób:

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

    Jeśli wymagaj aktualnego znacznika czasu:

    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()));
    
 112
Author: Paul Vargas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-02 12:40:39

Tl;dr

Z JDBC 4.2 lub nowszym i java 8 lub nowszym:
myPreparedStatement.setObject( … , myLocalDate  )

...i ...

myResultSet.getObject( … , LocalDate.class )

Szczegóły

Odpowiedź Vargasa jest dobra w wspominaniu o Javie.typy czasu, ale odnosi się tylko do konwersji do Javy.sql.Data. Nie ma potrzeby konwersji, jeśli Sterownik jest zaktualizowany.

Java.czas

Java.Framework time jest wbudowany w Javę 8 i nowszą. Klasy te zastępują stare kłopotliwe klasy date-time, takie jak java.util.Date, .Calendar, & java.text.SimpleDateFormat. Na zespół Joda-Time radzi również migrację do Javy.czas.

Aby dowiedzieć się więcej, Zobacz samouczek Oracle. I wyszukaj przepełnienie stosu dla wielu przykładów i wyjaśnień.

Większość Javy.funkcja czasu jest z powrotem przeniesiona do Java 6 i 7 w ThreeTen-Backport i dalej dostosowana do Androida w ThreeTenABP.

LocalDate

W Javie.time, the java.time.LocalDate Klasa reprezentuje wartość date-only bez time-of-day i bez Strefa czasowa.

Jeśli używasz sterownika JDBC zgodnego z JDBC 4.2 lub późniejszej specyfikacji, nie musisz używać starego java.sql.Date klasy. Możesz przekazać/pobrać LocalDate obiekty bezpośrednio do / z bazy danych poprzez PreparedStatement::setObject oraz ResultSet::getObject.

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

...i ...

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

Przed JDBC 4.2, Konwertuj

Jeśli sterownik nie obsługuje Javy.typy czasu bezpośrednio, wróć do konwersji do Javy.typy sql. Ale zminimalizować ich wykorzystanie, z Twoim logika biznesowa z wykorzystaniem tylko Javy.typy czasu.

Do starych klas dodano nowe metody konwersji do / Z Javy.typy czasu. Na java.sql.Date Zobacz też valueOf oraz toLocalDate metody.

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

...i ...

LocalDate localDate = sqlDate.toLocalDate();

Wartość zastępcza

Uważaj na używanie 0000-00-00 jako wartości zastępczej, jak pokazano w kodzie Twojego pytania. Nie wszystkie bazy danych i inne oprogramowanie poradzą sobie z cofaniem się tak daleko w czasie. Proponuję użyć czegoś takiego jak powszechnie używane Data odniesienia epoki Unix/Posix Z 1970 roku, 1970-01-01.

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

O Javie.CZAS

The java.CZAS framework jest wbudowany w Java 8 i nowsze. Klasy te zastępują kłopotliwe stare dziedzictwo klasy date-time, takie jak java.util.Date, Calendar, & SimpleDateFormat.

The Joda-CZAS projekt, obecnie w trybie konserwacji , radzi migrację do java.czas klasy.

Aby dowiedzieć się więcej, Zobacz samouczek Oracle. I wyszukaj przepełnienie stosu dla wielu przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Możesz wymienić Javę.obiekty time {[99] } bezpośrednio z bazą danych. Użyj sterownika JDBCzgodnego z JDBC 4.2 lub nowszego. Nie ma potrzeby stosowania łańcuchów, nie ma potrzeby stosowania klas java.sql.*.

Skąd pobrać Javę.zajęcia czasowe?

The ThreeTen-Extra projekt rozszerza Javę.czas z dodatkowymi zajęciami. Ten projekt jest poligonem dla potencjalnych przyszłych dodatków do Javy.czas. Możesz znaleźć tutaj kilka przydatnych klas, takich jak Interval, YearWeek, YearQuarter, i więcej .

 15
Author: Basil Bourque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-06 21:19:32

Problem polega na tym, że przekazujesz niezgodne formaty ze sformatowanej Javy.util.Date do zbudowania instancji java.sql.Date, które nie zachowują się w ten sam sposób podczas używania valueOf(), ponieważ używają różnych formatów.

Widzę również, że dążysz do utrzymywania godzin i minut, i myślę, że lepiej zmień typ danych na java.sql.Timestamp, który obsługuje godziny i minuty, wraz ze zmianą pola bazy danych na DATETIME lub podobne (w zależności od bazy danych sprzedawca).

W każdym razie, jeśli chcesz zmienić z java.util.Date to java.sql.Date, proponuję użyć

java.util.Date date = Calendar.getInstance().getTime();
java.sql.Date sqlDate = new java.sql.Date(date.getTime()); 
// ... more code here
prs.setDate(sqlDate);
 3
Author: Cristian Meneses,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 13:32:53

Docs wyraźnie mówi, że java.sql.Date rzuci:

  • IllegalArgumentException - Jeżeli podana data nie jest w formacie JDBC date escape (yyyy-[m]m-[d]d)

Również nie powinieneś konwertować daty na String, a następnie na sql.date, wydaje się to zbędne (i podatne na błędy!). Zamiast tego mógłbyś:

java.sql.Date sqlDate := new java.sql.Date(now.getTime());
prs.setDate(2, sqlDate);
prs.setDate(3, sqlDate);
 2
Author: Vincent Malgrat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 13:31:55

Jeśli chcesz dodać bieżącą datę do bazy danych, unikałbym obliczania daty w Javie na początek. Określenie "teraz" po stronie Javy (klienta) prowadzi do możliwych niespójności w bazie danych, jeśli strona klienta jest źle skonfigurowana, ma niewłaściwy czas, złą strefę czasową, itd. Zamiast tego, data może być ustawiona po stronie serwera w następujący sposób:

requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER ("   +
                "REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " +
                "VALUES(?, SYSDATE, SYSDATE + 30)";

...

prs.setInt(1, new Integer(requestID));

W ten sposób wymagany jest tylko jeden parametr bind, a Daty są obliczane po stronie serwera będą konsekwentnie. Jeszcze lepiej byłoby dodać insert trigger do CREDIT_REQ_TITLE_ORDER i mieć WYZWALACZ wstawić daty. Może to pomóc w wymuszeniu spójności między różnymi aplikacjami klienckimi (na przykład ktoś próbuje naprawić za pomocą sqlplus.

 1
Author: Glenn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-06 01:31:11

Nie jestem pewien, ale myślę, że szukasz stworzenia Javy.util.Date from a String, then convert that java.util.Randka na jawie.sql.Data.

Spróbuj tego:

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

}    

Zwróci Javę.sql.Obiekt Date dla setDate ();

Powyższa funkcja wyświetli długą wartość:

1375934400000

 -1
Author: Darth Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-09 06:06:05