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()
?
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 formacieyyyy-[m]m-[d]d
. np.:ps.setDate(2, java.sql.Date.valueOf("2013-09-04"));
-
java.util.Date
Załóżmy, że masz zmienną
endDate
typujava.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 formacieyyyy-[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
typujava.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()));
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.
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?
-
Java SE 8, Java SE 9, Java SE 10, i Później
- Wbudowany.
- część standardowego API Javy z dołączoną implementacją.
- Java 9 dodaje kilka drobnych funkcji i poprawek.
-
Java SE 6 oraz Java SE 7
- Większość Javy.funkcja czasu powraca-przeportowana do Java 6 i 7 w ThreeTen-Backport.
-
Android
- późniejsze wersje implementacji pakietu Android w Javie.zajęcia czasowe.
- dla wcześniejszego Androida ( ThreeTenABP projekt dostosowuje ThreeTen-Backport (wspomniane wyżej). Zobacz też jak stosować ThreeTenABP....
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 .
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);
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);
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.
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
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