Eu recebo uma exceção (veja abaixo) se eu tentar fazer
resultset.getString("add_date");
para uma conexão JDBC com um banco de dados MySQL contendo um valor DATETIME de 0000-00-00 00:00:00 (o valor quase nulo para DATETIME), embora eu esteja apenas tentando obter o valor como string, não como um objeto.
Eu contornei isso fazendo
SELECT CAST(add_date AS CHAR) as add_date
que funciona, mas parece bobo ... existe uma maneira melhor de fazer isso?
Meu ponto é que eu só quero a string DATETIME bruta, para que eu possa analisá-la como está .
observação: é aqui que entra o 0000: (de http://dev.mysql.com/doc/refman/5.0/en/datetime.html )
Valores ilegais de DATETIME, DATE ou TIMESTAMP são convertidos para o valor “zero” do tipo apropriado ('0000-00-00 00:00:00' ou '0000-00-00').
A exceção específica é 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)
Resposta alternativa, você pode usar este URL JDBC diretamente na configuração da sua fonte de dados:
jdbc:mysql://yourserver:3306/yourdatabase?zeroDateTimeBehavior=convertToNull
Editar:
Fonte: Manual MySQL
Atualização: Alexander relatou um bug que afeta o mysql-connector-5.1.15 nesse recurso. Veja CHANGELOGS no site oficial .
fonte
Isso me faz pensar que sua "solução alternativa" não é uma solução alternativa, mas na verdade a única maneira de obter o valor do banco de dados em seu código:
SELECT CAST(add_date AS CHAR) as add_date
A propósito, mais algumas notas da documentação do MySQL:
Restrições do MySQL em dados inválidos :
Tipos de data e hora do MySQL 5.x :
fonte
DATE_FORMAT(column name, '%Y-%m-%d %T') as dtime
Use isso para evitar o erro. Ele retorna a data em formato de string e então você pode obtê-la como uma string.
resultset.getString("dtime");
Isso realmente NÃO funciona. Mesmo que você chame getString. Internamente, o mysql ainda tenta convertê-lo para data primeiro.
fonte
Se, após adicionar linhas:
<property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property> hibernate.connection.zeroDateTimeBehavior=convertToNull <connection-property name="zeroDateTimeBehavior">convertToNull</connection-property>
continua a ser um erro:
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 linhas:
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
substitua pelas seguintes linhas, respectivamente:
1) Time.valueOf(resultSet.getString("time")); 2) Timestamp.valueOf(resultSet.getString("timestamp")); 3) Date.valueOf(resultSet.getString("date"));
fonte
Eu lutei com esse problema e implementei as soluções 'convertToNull' discutidas acima. Funcionou na minha instância local do MySql. Mas quando implantei meu aplicativo Play / Scala no Heroku, ele não funcionava mais. O Heroku também concatena vários argumentos à URL do banco de dados que eles fornecem aos usuários, e esta solução, por causa da concatenação de uso do Heroku de "?" antes de seu próprio conjunto de args, não funcionará. No entanto, encontrei uma solução diferente que parece funcionar igualmente bem.
SET sql_mode = 'NO_ZERO_DATE';
Coloquei isso nas descrições de minha tabela e resolveu o problema de '0000-00-00 00:00:00' não pode ser representado como java.sql.Timestamp
fonte
Eu sugiro que você use nulo para representar um valor nulo.
Qual é a exceção que você recebe?
BTW:
Não há um ano chamado 0 ou 0000. (embora algumas datas permitam este ano)
E não há 0 mês do ano ou 0 dia do mês. (Que pode ser a causa do seu problema)
fonte
Resolvi o problema considerando que '00 -00 -.... 'não é uma data válida, então, mudei minha definição de coluna SQL adicionando a expressão "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),...
Então, eu tenho que ser capaz de inserir valores NULL, que significa "Eu não registrei aquele timestamp ainda" ...
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),...
A 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 em ação:
@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(); }
Enfim todo o seu trabalho. Espero que ajude você.
fonte
Para adicionar às outras respostas: Se você não quiser a
0000-00-00
string, você pode usarnoDatetimeStringSync=true
(com a ressalva de sacrificar a conversão de fuso horário).O bug oficial do MySQL: https://bugs.mysql.com/bug.php?id=47108 .
Além disso, para histórico, o JDBC costumava retornar
NULL
para0000-00-00
datas, mas agora retorna uma exceção por padrão. Fontefonte
você pode anexar o url jdbc com
?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
Com a ajuda disso, sql convert '0000-00-00 00:00:00' como valor nulo.
por exemplo:
jdbc:mysql:<host-name>/<db-name>?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
fonte