Jeśli spróbuję, dostaję wyjątek (patrz poniżej)
resultset.getString("add_date");
dla połączenia JDBC z bazą danych MySQL zawierającą DATETIME wartość 0000-00-00 00:00:00 (quasi-zerowa wartość dla DATETIME), mimo że próbuję tylko uzyskać wartość jako ciąg, a nie jako obiekt.
Poradziłem sobie z tym, robiąc
SELECT CAST(add_date AS CHAR) as add_date
co działa, ale wydaje się głupie ... czy istnieje lepszy sposób na zrobienie tego?
Chodzi mi o to, że po prostu chcą surowego DATETIME ciąg, więc mogę sobie zanalizować to jak jest .
uwaga: tutaj pojawia się 0000: (z http://dev.mysql.com/doc/refman/5.0/en/datetime.html )
Niedozwolone wartości DATETIME, DATE lub TIMESTAMP są konwertowane na wartość „zero” 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)
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
Edytować:
Źródło: Podręcznik MySQL
Aktualizacja: Alexander zgłosił błąd dotyczący mysql-connector-5.1.15 w tej funkcji. Zobacz CHANGELOGS na oficjalnej stronie internetowej .
źródło
To sprawia, że myślę, że twoje „obejście” nie jest obejściem, ale w rzeczywistości jedynym sposobem na pobranie wartości z bazy danych do kodu:
SELECT CAST(add_date AS CHAR) as add_date
Przy okazji, kilka uwag z dokumentacji MySQL:
Ograniczenia MySQL dotyczące nieprawidłowych danych :
Typy daty i godziny MySQL 5.x :
źródło
DATE_FORMAT(column name, '%Y-%m-%d %T') as dtime
Użyj tego, aby uniknąć błędu. Zwraca datę w formacie ciągu, a następnie można ją pobrać jako ciąg.
resultset.getString("dtime");
To faktycznie NIE działa. Nawet jeśli wywołujesz metodę getString. Wewnętrznie mysql nadal najpierw próbuje przekonwertować go na datę.
źródło
Jeśli 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"));
źródło
Zmagałem się z tym problemem i zaimplementowałem omówione powyżej rozwiązania „convertToNull”. Zadziałało w mojej lokalnej instancji MySql. Ale kiedy wdrożyłem aplikację Play / Scala na Heroku, przestała działać. Heroku łączy również kilka argumentów z adresem URL bazy danych, które dostarczają użytkownikom, i to rozwiązanie, ponieważ Heroku używa konkatenacji „?” przed ich własnym zestawem argumentów, nie zadziała. Jednak znalazłem inne rozwiązanie, które wydaje się działać równie dobrze.
SET sql_mode = 'NO_ZERO_DATE';
Umieściłem to w moich opisach tabel i rozwiązało to problem „0000-00-00 00:00:00”, którego nie można przedstawić jako java.sql.
źródło
Sugeruję użycie wartości null do reprezentowania wartości zerowej.
Jaki wyjątek otrzymujesz?
BTW:
Nie ma roku o nazwie 0 lub 0000 (chociaż niektóre daty pozwalają na ten rok)
I nie ma 0 miesiąca w roku ani 0 dnia miesiąca. (Co może być przyczyną twojego problemu)
źródło
Rozwiązałem problem, biorąc pod uwagę, że „00 -00 -....” nie jest prawidłową datą, a następnie zmieniłem definicję kolumny SQL, dodając wyrażenie „NULL”, aby zezwolić na wartości null:
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 mogę 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(); }
Nareszcie cała jego praca. Mam nadzieję, że ci to pomoże.
źródło
Aby dodać do innych odpowiedzi: Jeśli nie chcesz
0000-00-00
ciągu, 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 .
Ponadto, dla historii, JDBC używany do powrotu
NULL
do0000-00-00
dat, ale teraz powrócić wyjątku domyślnie. Źródłoźródło
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” na wartość null.
na przykład:
jdbc:mysql:<host-name>/<db-name>?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
źródło