obsługa wartości DATETIME 0000-00-00 00: 00: 00 w JDBC

Dostaję wyjątek (patrz poniżej), jeśli próbuję zrobić

resultset.getString("add_date");

Dla połączenia JDBC z bazą danych MySQL zawierającą wartość DATETIME 0000-00-00 00: 00: 00 (quasi-null wartość dla DATETIME), mimo że próbuję uzyskać wartość jako string, a nie jako obiekt.

Obejrzałem to robiąc

SELECT CAST(add_date AS CHAR) as add_date
Co działa, ale wydaje się głupie... jest na to lepszy sposób?

Chodzi mi o to, że chcę tylko surowy łańcuch DATETIME, więc mogę sam go przeanalizować Jak jest .

Uwaga: Oto gdzie wchodzi 0000: (z http://dev.mysql.com/doc/refman/5.0/en/datetime.html )

Nielegalne DATETIME, Data lub znacznik czasu wartości są konwertowane na " zero" wartość odpowiedniego typu ('0000-00-00 00: 00: 00' lub '0000-00-00').

Szczególnym wyjątkiem jest ten:

SQLException: Cannot convert value '0000-00-00 00:00:00' from column 5 to TIMESTAMP.
SQLState: S1009
VendorError: 0
java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 5 to TIMESTAMP.
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at com.mysql.jdbc.ResultSetImpl.getTimestampFromString(ResultSetImpl.java:6343)
    at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5670)
    at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5491)
    at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5531)
Author: Jason S, 2009-04-23

10 answers

Natknąłem się na to, próbując rozwiązać ten sam problem. Instalacja, z którą pracuję wykorzystuje JBOSS i Hibernate, więc musiałem to zrobić w inny sposób. Dla podstawowego przypadku, powinieneś być w stanie dodać zeroDateTimeBehavior=convertToNull do Uri połączenia, jak na tej stronie Właściwości konfiguracji .

Znalazłem inne sugestie dotyczące umieszczenia tego parametru w konfiguracji hibernate:

In hibernate.cfg.xml :

<property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>

In hibernate.właściwości :

hibernate.connection.zeroDateTimeBehavior=convertToNull

Ale musiałem umieścić go w moim mysql-ds.plik xml dla JBOSS jako:

<connection-property name="zeroDateTimeBehavior">convertToNull</connection-property>
Mam nadzieję, że to komuś pomoże. :)
 80
Author: sarumont,
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-10-21 13:24:00

Alternatywna odpowiedź, możesz użyć tego adresu URL JDBC bezpośrednio w konfiguracji źródła danych:

jdbc:mysql://yourserver:3306/yourdatabase?zeroDateTimeBehavior=convertToNull

Edit:

Source: MySQL Manual

Datetimes with all-zero components (0000-00-00 ...)- Wartości te nie mogą być rzetelnie reprezentowane w Javie. Złącze / J 3.0.x zawsze konwertuje je na NULL podczas odczytu z ResultSet.

Connector / J 3.1 domyślnie wyświetla wyjątek, gdy te wartości są napotkane, ponieważ jest to najbardziej poprawne zachowanie zgodne ze standardami JDBC i SQL. To zachowanie można zmienić za pomocą właściwości konfiguracyjnej zerodatetimebehavior. Dopuszczalne wartości to:

  • wyjątek (domyślnie), który wyrzuca SQLException z SQLState s1009.
  • convertToNull , który zwraca NULL zamiast daty.
  • Runda , która zaokrągla datę do najbliższej najbliższej wartości, która wynosi 0001-01-01.

Aktualizacja: Alexander zgłosił błąd wpływający na mysql-connector-5.1.15 na tej funkcji. Zobacz CHANGELOGI na oficjalnej stronie internetowej .

 115
Author: Brian Clozel,
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-10-21 14:01:51

Chodzi mi o to, że chcę tylko surowy łańcuch DATETIME, więc mogę go przeanalizować tak, jak jest.

To sprawia, że myślę, że Twoje "obejście" nie jest obejściem, ale w rzeczywistości jedynym sposobem, aby uzyskać wartość z bazy danych do kodu:

SELECT CAST(add_date AS CHAR) as add_date

Przy okazji, kilka uwag z Dokumentacji MySQL:

MySQL ograniczenia niepoprawnych danych :

Przed MySQL 5.0.2, MySQL wybacza nielegalne lub niewłaściwe wartości danych i przymusza je do wartości prawnych dla wprowadzania danych. W MySQL 5.0.2 i nowszych, które pozostaje domyślnym zachowaniem, ale można zmienić tryb SQL serwera, aby wybrać bardziej tradycyjne traktowanie złych wartości, tak że serwer odrzuca je i przerywa instrukcję, w której występują.

[..]

Jeśli spróbujesz zapisać NULL do kolumny, która nie przyjmuje wartości NULL, wystąpi błąd dla instrukcji INSERT z jednym wierszem. Dla instrukcji INSERT wielowierszowych lub dla INSERT INTO ... Select statements, Serwer MySQL przechowuje domyślną wartość dla typu danych kolumny.

MySQL 5.x typy daty i czasu :

MySQL pozwala również na przechowywanie '0000-00-00' jako "dummy date" (jeśli nie używasz trybu NO_ZERO_DATE SQL). Jest to w niektórych przypadkach wygodniejsze (i zużywa mniej przestrzeni danych i indeksów) niż używanie wartości NULL.

[..]

Domyślnie, gdy MySQL napotka wartość dla Typu daty lub czasu, który jest poza zakresem lub w inny sposób nielegalne dla typu (jak opisano na początku tej sekcji), zamienia wartość na wartość "zero" dla tego typu.

 11
Author: Arjan,
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
2009-04-23 20:21:40
DATE_FORMAT(column name, '%Y-%m-%d %T') as dtime

Użyj tego, aby uniknąć błędu. Zwraca datę w formacie string, a następnie można ją uzyskać jako ciąg znaków.

resultset.getString("dtime");
To nie działa. Nawet jeśli nazywasz getString. Wewnętrznie mysql nadal próbuje przekonwertować go do daty jako pierwszy.
[[2]}w Kom.mysql.jdbc.WynikigetDateFromString (ResultSetImpl.java:2270)

~ [mysql-connector-java-5.1.15.jar: na] w Kom.mysql.jdbc.WynikigetStringInternal (ResultSetImpl.Java:5743)

~ [mysql-connector-java-5.1.15.jar: na] w Kom.mysql.jdbc.WynikigetString (ResultSetImpl.Java:5576)

~ [mysql-connector-java-5.1.15.jar: na]

 6
Author: hohner,
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-01-23 22:33:40

If, po dodaniu linii:

<property
name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>

hibernate.connection.zeroDateTimeBehavior=convertToNull

<connection-property
name="zeroDateTimeBehavior">convertToNull</connection-property>

Nadal jest błędem:

Illegal DATETIME, DATE, or TIMESTAMP values are converted to the “zero” value of the appropriate type ('0000-00-00 00:00:00' or '0000-00-00').

Znajdź linie:

1) resultSet.getTime("time"); // time = 00:00:00
2) resultSet.getTimestamp("timestamp"); // timestamp = 00000000000000
3) resultSet.getDate("date"); // date = 0000-00-00 00:00:00

Zastąpić odpowiednio następującymi wierszami:

1) Time.valueOf(resultSet.getString("time"));
2) Timestamp.valueOf(resultSet.getString("timestamp"));
3) Date.valueOf(resultSet.getString("date"));
 5
Author: Vadim,
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
2012-01-09 15:19:21

Zmagałem się z tym problemem i zaimplementowałem omówione powyżej rozwiązania "convertToNull". To działało w mojej lokalnej instancji MySql. Ale kiedy wdrożyłem moją aplikację Play / Scala do Heroku, nie będzie już działać. Heroku łączy również kilka args do adresu URL DB, który dostarczają użytkownikom, A To rozwiązanie, ze względu na użycie Heroku konkatenacja"?"przed własnym zestawem args, nie będzie działać. Znalazłem jednak inne rozwiązanie, które wydaje się działać równie dobrze.

SET SQL_MODE = "NO_ZERO_DATE";

Umieściłem to w opisach tabeli i rozwiązało to problem '0000-00-00 00: 00: 00' nie może być reprezentowany jako java.sql.Timestamp

 5
Author: Aqume,
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-01-15 23:37:52

Sugeruję użycie null do reprezentowania wartości null.

Jaki masz wyjątek?

BTW:

Nie ma roku o nazwie 0 lub 0000. (Choć niektóre daty pozwalają w tym roku)

I nie ma 0 miesiąca roku ani 0 dnia miesiąca. (Co może być przyczyną twojego problemu)

 3
Author: Peter Lawrey,
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
2009-04-23 19:43:35

Rozwiązałem problem rozważając '00-00-....'isn' is a valid date, then, I changed my SQL column definition adding" NULL " expresion to permit null values:

SELECT "-- Tabla item_pedido";
CREATE TABLE item_pedido (
    id INTEGER AUTO_INCREMENT PRIMARY KEY,
    id_pedido INTEGER,
    id_item_carta INTEGER,
    observacion VARCHAR(64),
    fecha_estimada TIMESTAMP,
    fecha_entrega TIMESTAMP NULL, // HERE IS!!.. NULL = DELIVERY DATE NOT SET YET
    CONSTRAINT fk_item_pedido_id_pedido FOREIGN KEY (id_pedido)
        REFERENCES pedido(id),...

Następnie muszę być w stanie wstawić wartości NULL, co oznacza "nie zarejestrowałem jeszcze tego znacznika czasu"...

SELECT "++ INSERT item_pedido";
INSERT INTO item_pedido VALUES
(01, 01, 01, 'Ninguna', ADDDATE(@HOY, INTERVAL 5 MINUTE), NULL),
(02, 01, 02, 'Ninguna', ADDDATE(@HOY, INTERVAL 3 MINUTE), NULL),...

Tabela wygląda tak:

mysql> select * from item_pedido;
+----+-----------+---------------+-------------+---------------------+---------------------+
| id | id_pedido | id_item_carta | observacion | fecha_estimada      | fecha_entrega       |
+----+-----------+---------------+-------------+---------------------+---------------------+
|  1 |         1 |             1 | Ninguna     | 2013-05-19 15:09:48 | NULL                |
|  2 |         1 |             2 | Ninguna     | 2013-05-19 15:07:48 | NULL                |
|  3 |         1 |             3 | Ninguna     | 2013-05-19 15:24:48 | NULL                |
|  4 |         1 |             6 | Ninguna     | 2013-05-19 15:06:48 | NULL                |
|  5 |         2 |             4 | Suave       | 2013-05-19 15:07:48 | 2013-05-19 15:09:48 |
|  6 |         2 |             5 | Seco        | 2013-05-19 15:07:48 | 2013-05-19 15:12:48 |
|  7 |         3 |             5 | Con Mayo    | 2013-05-19 14:54:48 | NULL                |
|  8 |         3 |             6 | Bilz        | 2013-05-19 14:57:48 | NULL                |
+----+-----------+---------------+-------------+---------------------+---------------------+
8 rows in set (0.00 sec)

Wreszcie: JPA w akcji:

@Stateless
@LocalBean
public class PedidosServices {
    @PersistenceContext(unitName="vagonpubPU")
    private EntityManager em;

    private Logger log = Logger.getLogger(PedidosServices.class.getName());

    @SuppressWarnings("unchecked")
    public List<ItemPedido> obtenerPedidosRetrasados() {
        log.info("Obteniendo listado de pedidos retrasados");
        Query qry = em.createQuery("SELECT ip FROM ItemPedido ip, Pedido p WHERE" +
                " ip.fechaEntrega=NULL" +
                " AND ip.idPedido=p.id" +
                " AND ip.fechaEstimada < :arg3" +
                " AND (p.idTipoEstado=:arg0 OR p.idTipoEstado=:arg1 OR p.idTipoEstado=:arg2)");
        qry.setParameter("arg0", Tipo.ESTADO_BOUCHER_ESPERA_PAGO);
        qry.setParameter("arg1", Tipo.ESTADO_BOUCHER_EN_SERVICIO);
        qry.setParameter("arg2", Tipo.ESTADO_BOUCHER_RECIBIDO);
        qry.setParameter("arg3", new Date());

        return qry.getResultList();
    }
W końcu cała jego praca. Mam nadzieję, że ci to pomoże.
 2
Author: EdU,
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-05-19 18:17:39

Aby dodać do pozostałych odpowiedzi: jeśli chcesz 0000-00-00, możesz użyć noDatetimeStringSync=true (z zastrzeżeniem poświęcenia konwersji strefy czasowej).

Oficjalny błąd MySQL: https://bugs.mysql.com/bug.php?id=47108 .

Również w przypadku historii, JDBC zwracało NULL dla 0000-00-00 dat, ale teraz domyślnie zwraca wyjątek. Źródło

 2
Author: damio,
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-01-29 02:13:48

Możesz dołączyć adres URL jdbc za pomocą

?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8

Z pomocą tego, SQL konwertuje '0000-00-00 00:00:00' jako wartość null.

Eg:

jdbc:mysql:<host-name>/<db-name>?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
 2
Author: Mukul Aggarwal,
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-23 08:12:05