【问题标题】:MySQL DATETIME precision (joda-time, Hibernate, org.jadira.usertype, hbm2ddl)MySQL DATETIME 精度(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 以毫秒精度从数据库中写入和读取。

【问题讨论】:

    标签: java mysql hibernate jodatime hbm2ddl


    【解决方案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。
      猜你喜欢
      • 2011-09-11
      • 2015-07-11
      • 2021-11-11
      • 2012-06-05
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 2015-01-24
      • 2013-05-03
      相关资源
      最近更新 更多