Recibo una excepción (ver más abajo) si trato de hacer
resultset.getString("add_date");
para una conexión JDBC a una base de datos MySQL que contiene un valor DATETIME de 0000-00-00 00:00:00 (el valor cuasi nulo para DATETIME), aunque solo estoy tratando de obtener el valor como una cadena, no como un objeto.
Me las arreglé haciendo
SELECT CAST(add_date AS CHAR) as add_date
que funciona, pero parece una tontería ... ¿hay una mejor manera de hacer esto?
Mi punto es que solo quiero la cadena DATETIME sin procesar, para poder analizarla yo mismo como está .
nota: aquí es donde entra el 0000: (de http://dev.mysql.com/doc/refman/5.0/en/datetime.html )
Los valores ilegales DATETIME, DATE o TIMESTAMP se convierten al valor "cero" del tipo apropiado ('0000-00-00 00:00:00' o '0000-00-00').
La excepción específica es esta:
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)
Respuesta alternativa, puede usar esta URL de JDBC directamente en la configuración de su fuente de datos:
jdbc:mysql://yourserver:3306/yourdatabase?zeroDateTimeBehavior=convertToNull
Editar:
Fuente: Manual MySQL
Actualización: Alexander informó un error que afectaba a mysql-connector-5.1.15 en esa función. Consulte CHANGELOGS en el sitio web oficial .
fuente
Eso me hace pensar que su "solución alternativa" no es una solución alternativa, sino que, de hecho, es la única forma de obtener el valor de la base de datos en su código:
SELECT CAST(add_date AS CHAR) as add_date
Por cierto, algunas notas más de la documentación de MySQL:
Restricciones de MySQL sobre datos no válidos :
Tipos de fecha y hora de MySQL 5.x :
fuente
DATE_FORMAT(column name, '%Y-%m-%d %T') as dtime
Use esto para evitar el error. Devuelve la fecha en formato de cadena y luego puede obtenerla como una cadena.
resultset.getString("dtime");
En realidad, esto NO funciona. Aunque llame a getString. Internamente, mysql todavía intenta convertirlo a la fecha primero.
fuente
Si, después de agregar líneas:
<property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property> hibernate.connection.zeroDateTimeBehavior=convertToNull <connection-property name="zeroDateTimeBehavior">convertToNull</connection-property>
sigue siendo un error:
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').
encontrar líneas:
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
reemplazar con las siguientes líneas, respectivamente:
1) Time.valueOf(resultSet.getString("time")); 2) Timestamp.valueOf(resultSet.getString("timestamp")); 3) Date.valueOf(resultSet.getString("date"));
fuente
Luché con este problema e implementé las soluciones 'convertToNull' discutidas anteriormente. Funcionó en mi instancia local de MySql. Pero cuando implementé mi aplicación Play / Scala en Heroku, ya no funcionaba. Heroku también concatena varios argumentos a la URL de la base de datos que proporcionan a los usuarios, y esta solución, debido a la concatenación de uso de Heroku de "?" antes de su propio conjunto de argumentos, no funcionará. Sin embargo, encontré una solución diferente que parece funcionar igualmente bien.
SET sql_mode = 'NO_ZERO_DATE';
Puse esto en las descripciones de mi tabla y resolvió el problema de '0000-00-00 00:00:00' no se puede representar como java.sql.Timestamp
fuente
Le sugiero que use nulo para representar un valor nulo.
¿Cuál es la excepción que obtienes?
Por cierto:
No hay un año llamado 0 o 0000 (aunque algunas fechas permiten este año)
Y no hay 0 mes del año ni 0 día del mes. (Que puede ser la causa de su problema)
fuente
Resolví el problema considerando que '00 -00 -.... 'no es una fecha válida, luego, cambié la definición de mi columna SQL agregando la expresión "NULL" para permitir valores nulos:
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),...
Entonces, tengo que poder insertar valores NULL, eso significa "No registré esa marca de tiempo todavía" ...
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),...
La mesa parece que:
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)
Finalmente: JPA en acción:
@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(); }
Por fin todo su trabajo. Espero que te ayude.
fuente
Para agregar a las otras respuestas: si desea la
0000-00-00
cadena, puede usarnoDatetimeStringSync=true
(con la advertencia de sacrificar la conversión de zona horaria).El error oficial de MySQL: https://bugs.mysql.com/bug.php?id=47108 .
Además, para el historial, JDBC solía regresar
NULL
para las0000-00-00
fechas, pero ahora devuelve una excepción de forma predeterminada. Fuentefuente
puede agregar la url jdbc con
?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
Con la ayuda de esto, sql convierte '0000-00-00 00:00:00' como valor nulo.
p.ej:
jdbc:mysql:<host-name>/<db-name>?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
fuente