我将MySQL 5.1社区服务器更新为5.6。在此之后,我遇到了奇怪的DATETIME(休眠类型时间戳)行为。出于某种原因,在保存hibernate映射对象后,我的日期从(例如)'2012-09-30 23:59:59'变为'2012-10-1 00:00:00'。我的日志说我确实在午夜之前保存了一秒钟,但是当我查看数据库时它已经改为第二天的开头。如果我使用相同的日期创建一个INSERT查询,它可以正常工作。
根据MySQL文档,不应该使用DATETIME进行任何时区转换。我还测试了MySQL 5.5,我无法重现同样的问题。
我的hbm映射看起来像这样:
<composite-id>
...
<key-property name="timestamp" type="timestamp" column="timestamp"/>
</composite-id>
编辑:我也有最新的MySQL jdbc驱动程序。
编辑2:你可以看到日期的变化。
22.04.13 12:04:54.149 DEBUG SQL:104 - insert into data_table (col_1, col_2, timestamp) values (?, ?, ?)
22.04.13 12:04:54.149 TRACE BasicBinder:83 - binding parameter [1] as [DOUBLE] - 1.0
22.04.13 12:04:54.149 TRACE BasicBinder:83 - binding parameter [2] as [INTEGER] - 1
22.04.13 12:04:54.150 TRACE BasicBinder:83 - binding parameter [3] as [TIMESTAMP] - Mon Apr 22 23:59:59 EEST 2013
22.04.13 12:04:54.151 ERROR SqlExceptionHelper:144 - Duplicate entry '1-2013-04-23 00:00:00' for key 'PRIMARY'
编辑3:使用Hibernate版本3.3.1和4.1.9再现问题。
答案 0 :(得分:6)
我想我找到了答案。我使用的日期包括毫秒,似乎在MySQL 5.6中你必须定义DATETIME的准确性。在没有定义小数减数的数量的情况下,它默认为0.在这种情况下,'2013-04-01 23:59:59.500'轮到'2013-04-02 00:00:00'。我设法用sql查询重现这个,所以它与Java或Hibernate没有任何关系。
http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
我在代码中更改了一行
calendar.set(GregorianCalendar.MILLISECOND, 999);
到
calendar.set(GregorianCalendar.MILLISECOND, 0);
问题消失了。