java.util.Date vs java.sql.Data

java.util.Date vs java.sql.Date: Kiedy używać which I dlaczego?

Author: Jonas, 2010-02-21

5 answers

Gratulacje, trafiłeś w Moje ulubione pet peeve z JDBC: date class handling.

Zasadniczo bazy danych Zwykle obsługują co najmniej trzy formy pól datetime, które są datą, czasem i znacznikiem czasu. Każda z nich ma odpowiednią klasę w JDBC i każda z nich rozszerza java.util.Date. Szybkie semantyki każdego z tych trzech są następujące:

  • java.sql.Date odpowiada dacie SQL, co oznacza, że przechowuje lata, miesiące i dni while godzina, minuta, sekunda i milisekunda są ignorowane. Dodatkowo sql.Date nie jest powiązane ze strefami czasowymi.
  • java.sql.Time odpowiada czasowi SQL i jak powinno być oczywiste, zawiera jedynie informacje o godzinie, minutach, sekundach i milisekundach .
  • java.sql.Timestamp odpowiada znacznikowi czasu SQL, który jest dokładną datą nanosekundy (zauważ, że util.Date obsługuje tylko milisekundy!) z możliwością dostosowania precyzja.

Jednym z najczęstszych błędów podczas używania sterowników JDBC w odniesieniu do tych trzech typów jest to, że typy są obsługiwane nieprawidłowo. oznacza to, że sql.Date jest strefą czasową, sql.Time zawiera bieżący rok, miesiąc, dzień itd.

Wreszcie: którego użyć?

Zależy od typu SQL pola, naprawdę. PreparedStatement ma ustawiacze dla wszystkich trzech wartości, #setDate() jest jednym dla sql.Date, #setTime() dla sql.Time i #setTimestamp() dla sql.Timestamp.

Zauważ, że jeśli użyjesz ps.setObject(fieldIndex, utilDateObject);, możesz dać normalny util.Date większości sterowników JDBC, które z radością pożrą go tak, jakby był odpowiedniego typu, ale Kiedy poprosisz o Dane później, możesz zauważyć, że faktycznie brakuje ci rzeczy.

Naprawdę mówię, że żadna z dat nie powinna być w ogóle używana.

O czym mówię, Zapisz milisekundy / nanosekundy jako zwykłe długie i przekonwertuj je na dowolne obiekty, których używasz (obowiązkowa wtyczka Joda-time). Jednym z hakerskich sposobów, które można zrobić, jest przechowywanie komponentu date jako jednego długiego i czasowego jako drugiego, na przykład teraz będzie to 20100221 i 154536123. Te magiczne liczby mogą być używane w zapytaniach SQL i będą przenośne z bazy danych do innej i pozwolą całkowicie uniknąć tej części JDBC / Java date API: S.

 543
Author: Esko,
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
2015-03-04 19:21:52

LATE EDIT: począwszy od Javy 8 powinieneś używać ani java.util.Date ani java.sql.Date, jeśli w ogóle możesz tego uniknąć, a zamiast tego wolisz używać java.time pakiet (oparty na Joda), a nie cokolwiek innego. Jeśli nie jesteś na Javie 8, Oto oryginalna odpowiedź:


java.sql.Date - podczas wywoływania metod / konstruktorów bibliotek, które go używają (jak JDBC). Nie inaczej. Nie chcesz wprowadzać zależności do bibliotek baz danych dla aplikacji/modułów, które nie jawnie radzić sobie z JDBC.

java.util.Date - podczas korzystania z bibliotek, które go używają. W przeciwnym razie, jak najmniej, z kilku powodów:

  • Jest zmienny, co oznacza, że musisz wykonać kopię obronną za każdym razem, gdy przekazujesz ją do metody lub zwracasz z niej.

  • To nie obsługuje daty bardzo dobrze, co zacofani ludzie jak yours truly, uważają, że zajęcia obsługi daty powinny.

  • Teraz, ponieważ J. U. D nie wykonuje tej pracy Bardzo wprowadzono upiorne klasy. Są one również mutowalne i okropne w pracy, i należy ich unikać, jeśli nie masz wyboru.

  • Istnieją lepsze alternatywy, takie jak Joda Time API (może nawet trafić do Javy 7 i stać się nowym oficjalnym API obsługi dat - A quick search mówi, że nie będzie).

Jeśli uważasz, że wprowadzenie nowej zależności jak Joda jest przesadą, longs nie są takie złe dla Użyj dla pól znaczników czasu w obiektach, chociaż sam Zwykle zawijam je w j. u. D podczas ich przekazywania, dla bezpieczeństwa typu i jako dokumentacja.

 52
Author: gustafc,
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-23 12:26:38

Jedyny czas, aby użyć java.sql.Date jest w PreparedStatement.setDate. W przeciwnym razie użyj java.util.Date. Mówi, że ResultSet.getDate zwraca java.sql.Date, ale może być przypisany bezpośrednio do java.util.Date.

 17
Author: Paul Tomblin,
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
2016-08-30 16:45:02

Miałem ten sam problem, najprostszym sposobem, jaki znalazłem, aby wstawić bieżącą datę do przygotowanego oświadczenia jest ten:

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));
 10
Author: Israelm,
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-07-16 20:16:24

Java.util.Klasa Date w Javie reprezentuje określony moment w czasie (e,.g., 2013 Nov 25 16: 30: 45 do milisekund), ale typ danych DATE w DB reprezentuje tylko datę (np., 2013 Nov 25). Aby uniemożliwić dostarczanie oprogramowania java.util.Obiekt Date do DB przez pomyłkę Java nie pozwala ustawić parametru SQL na java.util.Data bezpośrednio:

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work

Ale nadal pozwala to zrobić siłą / intencją(wtedy godziny i minuty będą ignorowane przez sterownik DB). To jest skończyłem z Javą.sql.Klasa daty:

PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work

Java.sql.Obiekt Date może przechowywać moment w czasie (dzięki czemu jest łatwy do skonstruowania z Javy.util.Data), ale rzuci wyjątek, jeśli spróbujesz poprosić go o godziny (aby wymusić jego koncepcję bycia datą tylko). Oczekuje się, że sterownik DB rozpozna tę klasę i po prostu użyje 0 dla godzin. Spróbuj tego:

public static void main(String[] args) {
  java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
  java.sql.Date d2 = new java.sql.Date(12345);
  System.out.println(d1.getHours());
  System.out.println(d2.getHours());
}
 2
Author: Kent Tong,
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-11-22 04:26:17