MySQL DATETIME 精度(joda-time、Hibernate、org.jadira.usertype、hbm2ddl)

Posted

技术标签:

【中文标题】MySQL DATETIME 精度(joda-time、Hibernate、org.jadira.usertype、hbm2ddl)【英文标题】:MySQL DATETIME precision (joda-time, Hibernate, org.jadira.usertype, hbm2ddl) 【发布时间】:2014-05-12 04:21:45 【问题描述】:

在我的 hibernate-4 实体中,我正在使用推荐的 jadira usertypes 映射一个 joda-time DateTime 属性:

@Entity
@Table(name="timing")
public class TimingEntity 
    ...
    @Basic(optional=false)
    @Column(name="moment")
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    public DateTime getMoment() 
       ...

我的数据库是 mysql。将休眠属性hbm2ddl.auto 设置为create 值,我在timing 表中生成了以下列:

CREATE TABLE `timing` (
    ...
   `moment` DATETIME NOT NULL,
    ...
)

生成的CREATE TABLE 包含 DATETIME 列。 MySQL 中的 DATETIME 只有秒精度,没有小数部分。为了启用小数部分,最多为微秒,MySQL 5.6.4 和更高版本的enablesDATETIME(precision) 列,例如DATETIME(3) 具有毫秒精度。

我的问题是——有没有办法为我用 hbm2ddl 生成的时间字段指定精度?至少,这是 jadira 用户类型、java.sql 还是 jdbc 驱动程序机制的问题?

PS 当我手动修改数据库表以获得我想要的精确列精度时,例如 DATETIME(3),一切正常 - joda DateTimes 以毫秒精度从数据库中写入和读取。

【问题讨论】:

【参考方案1】:

我发现了另一种解决方案,它不允许在 @Column 注释中对 MySQL 列定义 sn-p 进行硬编码。通过覆盖org.hibernate.dialect.MySQLDialect来定义你自己的hibernate方言:

package org.yourproject;

import java.sql.Types;
import org.hibernate.dialect.MySQL5Dialect;

public class MySQL564PlusDialect extends MySQL5Dialect 
   public MySQL564PlusDialect() 
      super();
      registerColumnType( Types.TIMESTAMP, 6, "datetime($l)" );
   

并将其指定为休眠属性hibernate.dialect=org.yourproject.MySQL564PlusDialect(您要扩展的方言可能会有所不同,例如改为org.hibernate.dialect.MySQL5InnoDBDialect)。

现在您可以使用length 属性在@Column 注释中调整DATETIME 的精度:

@Basic(optional=false)
@Column(name="moment", length=3)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime getMoment() 
 ...

这将产生DATETIME(3) 列定义,意思是毫秒精度。如果您需要简单的DATETIME(没有小数秒),请不要指定长度。您可以使用高达 6 的 length 值,这意味着微秒精度。

如果您碰巧使用了与上述不同的方言(例如标准org.hibernate.dialect.MySQLDialect 或其他数据库),这不会破坏您的代码:@Column 上的length 属性将被忽略。

附:使用@Columnprecision 属性而不是length 会更明智,但是在我自己的方言实现中用"datetime($p)" 简单地替换"datetime($l)" 模式并不适用。

【讨论】:

【参考方案2】:

使用可以为它使用@Column#columnDefinition属性

@Basic(optional=false)
@Column(name="moment" columnDefinition="DATETIME(3) NOT NULL")
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime getMoment() 
   
   ...

您也可以尝试@Column#precision 属性,但在文档中写道,这仅适用于小数。

【讨论】:

成功了,谢谢! columnDefinition 有效,precision 无效。然而,缺点是我开始在我的代码中依赖 mysql。

以上是关于MySQL DATETIME 精度(joda-time、Hibernate、org.jadira.usertype、hbm2ddl)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL数据类型 - 日期和时间类型

MySQL数据类型 - 日期和时间类型

如何在 C# 中使用 DateTime.Now.Ticks 保持精度

SQL Server Compact 4.0 DateTime 精度不包括秒

Entity Framework 和 DateTime 的毫秒精度比较

如何将 DateTime 转换为精度大于 T-SQL 中天数的数字?