如果我尝试
,我会遇到异常(见下文)resultset.getString("add_date");
对于包含DATETIME值为00:00:00(DATETIME的准空值)的MySQL数据库的JDBC连接,即使我只是想将值作为字符串获取,不是一个对象。
我通过做
来解决这个问题SELECT CAST(add_date AS CHAR) as add_date
有效,但看起来很傻......有更好的方法吗?
我的观点是我只想要原始的DATETIME字符串,所以我可以自己解析,。
注意:这里是0000的来源:(来自http://dev.mysql.com/doc/refman/5.0/en/datetime.html)
非法DATETIME,DATE或TIMESTAMP 值转换为“零” 适当类型的值 ('00:00:00'或' '0000-00-00')。
具体例外是这一个:
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)
答案 0 :(得分:120)
替代答案,您可以直接在数据源配置中使用此JDBC URL:
jdbc:mysql://yourserver:3306/yourdatabase?zeroDateTimeBehavior=convertToNull
编辑:
使用全零组件的日期时间(0000-00-00) - 这些值无法在Java中可靠地表示。从ResultSet读取时,Connector / J 3.0.x始终将它们转换为NULL。
当遇到这些值时,Connector / J 3.1默认会抛出异常,因为根据JDBC和SQL标准,这是最正确的行为。可以使用zeroDateTimeBehavior配置属性修改此行为。允许值为:
- 异常(默认值),抛出SQLException,SQLState为S1009。
- convertToNull ,返回NULL而不是日期。
- round ,将日期四舍五入到最接近的值0001-01-01。
更新:亚历山大在该功能上报告了一个影响mysql-connector-5.1.15的错误。请参阅CHANGELOGS on the official website。
答案 1 :(得分:81)
我偶然发现了这个试图解决同样问题的事情。我正在使用的安装使用JBOSS和Hibernate,所以我必须采用不同的方式。对于基本情况,您应该可以根据此configuration properties page将zeroDateTimeBehavior=convertToNull
添加到您的连接URI。
我发现其他建议涉及将该参数放入你的hibernate配置中:
在 hibernate.cfg.xml :
中<property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
在 hibernate.properties :
中hibernate.connection.zeroDateTimeBehavior=convertToNull
但是我必须把它放在我的 mysql-ds.xml 文件中,用于JBOSS:
<connection-property name="zeroDateTimeBehavior">convertToNull</connection-property>
希望这有助于某人。 :)
答案 2 :(得分:11)
我的观点是我只想要原始的DATETIME字符串,所以我可以自己解析它。
这让我觉得你的“解决方法”不是一种解决方法,但实际上是从数据库中获取代码的唯一方法:
SELECT CAST(add_date AS CHAR) as add_date
顺便提一下,MySQL文档中还有一些注释:
MySQL Constraints on Invalid Data:
在MySQL 5.0.2之前,MySQL可以容忍非法或不正确的数据值,并强制它们为数据输入的合法值。在MySQL 5.0.2及更高版本中,这仍然是默认行为,但您可以更改服务器SQL模式以选择更传统的错误值处理方式,以便服务器拒绝它们并中止它们出现的语句。
[..]
如果尝试将NULL存储到不接受NULL值的列中,则单行INSERT语句会发生错误。对于多行INSERT语句或INSERT INTO ... SELECT语句,MySQL Server存储列数据类型的隐式默认值。
MySQL 5.x Date and Time Types:
MySQL还允许您将“0000-00-00”存储为“虚拟日期”(如果您没有使用NO_ZERO_DATE SQL模式)。在某些情况下,这比使用NULL值更方便(并且使用更少的数据和索引空间)。
[..]
默认情况下,当MySQL遇到超出范围的日期或时间类型的值或者该类型非法时(如本节开头所述),它会将值转换为“零”值那种类型。
答案 3 :(得分:6)
DATE_FORMAT(column name, '%Y-%m-%d %T') as dtime
使用此选项可避免错误。它以字符串格式返回日期,然后您可以将其作为字符串。
resultset.getString("dtime");
这实际上不起作用。即使你调用getString。内部mysql仍然首先尝试将其转换为日期。
在com.mysql.jdbc.ResultSetImpl.getDateFromString(ResultSetImpl.java:2270)
com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5743)〜[mysql-connector-java-5.1.15.jar:na]
com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5576)〜[mysql-connector-java-5.1.15.jar:na]
〜[MySQL的连接器的Java-5.1.15.jar:NA]
答案 4 :(得分:5)
如果在添加行之后:
<property
name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
hibernate.connection.zeroDateTimeBehavior=convertToNull
<connection-property
name="zeroDateTimeBehavior">convertToNull</connection-property>
仍然是一个错误:
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').
找到行:
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
分别替换以下行:
1) Time.valueOf(resultSet.getString("time"));
2) Timestamp.valueOf(resultSet.getString("timestamp"));
3) Date.valueOf(resultSet.getString("date"));
答案 5 :(得分:5)
我解决了这个问题并实现了上面讨论的'convertToNull'解决方案。它在我的本地MySql实例中工作。但是当我将我的Play / Scala应用程序部署到Heroku时,它不再有效。 Heroku还将几个args连接到他们为用户提供的DB URL,这个解决方案,因为Heroku使用了串联“?”在他们自己的一套args之前,将无法正常工作。然而,我发现了一种似乎同样有效的不同解决方案。
SET sql_mode ='NO_ZERO_DATE';
我把它放在我的表格描述中它解决了'0000-00-00 00:00:00'的问题不能表示为java.sql.Timestamp
答案 6 :(得分:3)
我建议你用null来表示一个空值。
你得到的例外是什么?
BTW:
没有一年被称为0或0000.(虽然有些日期允许今年)
一年中没有0个月或0个月。 (这可能是导致您出现问题的原因)
答案 7 :(得分:3)
我解决了考虑'00 -00 -....'不是有效日期的问题,然后,我更改了我的SQL列定义,添加了“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),...
然后,我将能够插入NULL值,这意味着“我还没有注册该时间戳”......
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),...
表格显示:
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)
最后:JPA在行动:
@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();
}
最后所有的工作。我希望能帮助你。
答案 8 :(得分:2)
要添加其他答案:如果您需要noDatetimeStringSync=true
字符串,则可以使用NULL
(但需要注意牺牲时区转换)。
官方MySQL错误:https://bugs.mysql.com/bug.php?id=47108。
此外,对于历史记录,JDBC过去常常为0000-00-00
日期返回$modal.open({
templateUrl: filepath,
controller: controllerName,
scope: $scope
})
.result.then(function () {
alert('closed');
}, function () {
alert('canceled');
});
,但现在默认返回异常。
Source
答案 9 :(得分:2)
您可以使用
附加jdbc网址?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8
借助于此,sql将'0000-00-00 00:00:00'转换为空值。
例如:
jdbc:mysql:<host-name>/<db-name>?zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8