2012-12-06 77 views
3

我在使用MySql创建时间戳时遇到问题。根据here的建议,未使用@DatabaseField定义中的特定DataType.TIME_STAMP条目。MySQL创建时间戳的ORMLite问题

我现在@DatabaseField看起来是这样的:

@DatabaseField(format="yyyy-MM-dd HH:mm:ss", defaultValue="CURRENT_TIMESTAMP") 
private Timestamp updatedAt; 

表仍然得到错误创建:

Unable to create table because of [Problems parsing default date 
string 'CURRENT_TIMESTAMP' using 'yyyy-MM-dd HH:mm:ss.SSSSSS'] 

所以它似乎忽略格式定义,没有格式定义,我仍然得到这个错误:

Unable to create table because of [Problems parsing default date 
string 'CURRENT_TIMESTAMP' using 'yyyy-MM-dd HH:mm:ss.SSSSSS'] 

我试过指定dataType,c挂到DATE_TIME等。我还没有找到一个组合(除了不使用时间戳,只是创建一个DATE_TIME,它的工作原理,但不是与CURRENT_TIMESTAMP)。

我真的陷入困境,因为我过去手动更新了表,但现在数量在不断增加,我希望使用ORMLite中的创建表选项完全自动化,而不必稍后手动混淆架构。

任何指针将非常欢迎如何得到这个工作。

+0

有可能是一个消息安东尼问题在这里问题是''CURRENT_TIMESTAMP''不能用作默认值,因为它与转换模式不匹配。不知怎的,我想我需要特殊情况。由于每种数据库类型都有不同的表现,这将是一个痛苦。 – Gray

+0

哇!感谢Grey的超快反应。我理解这个问题,对待它的一种方式是让用户弄清楚它?如果你把MySQL版本放到Postres中,表格创建自然会失败。所以如果你看到我的意思,那么这是一个类设计问题,而不是基础设施问题。也许只是简单地接受在DefaultValue字段中输入的任何内容,仅适用于时间戳?用户有责任让它正确。那对你有用吗? – Anthony

+0

是的,这可能是正确的解决方案。 _perfect_解决方案应该在抽象数据库类型上有某种Timestamp验证器。 :-)我其实有点惊讶,它需要做字符串解析。我今天晚些时候会看。 – Gray

回答

3

现在看来除了使用不适用于Timestamp字段的@DatabaseFiled(version = true)之外,看起来并不是一种方法。这已得到纠正在树干和将在4.46合作:

http://ormlite.com/docs/version-field

为了得到它与时间戳字段在4.45的工作是非常每个虽然。您需要extends TimeStampType并覆盖以下方法。看到这个答案的底部,了解详情:

@Override 
public Object moveToNextValue(Object currentValue) { 
    long newVal = System.currentTimeMillis(); 
    if (currentValue == null) { 
     return new java.sql.Timestamp(newVal); 
    } else if (newVal == ((java.sql.Timestamp) currentValue).getTime()) { 
     return new java.sql.Timestamp(newVal + 1L); 
    } else { 
     return new java.sql.Timestamp(newVal); 
    } 
} 

然后指定你的领域为:

@DatabaseField(persisterClass = LocalCurrentTimeStampType.class, version = true) 
java.sql.Timestamp timestamp; 

[用于创建日期,但不为其他更新以下工作。我会留下它的一般信息。]]

这是非平凡的,但我终于想出了你可以做到这一点,使用最新版本的干线。在4.46中,我们将为只有只读字段的@DatabaseField(readOnly = true)添加支持。这允许你说:

@DatabaseField(defaultValue = "CURRENT_TIMESTAMP()", readOnly = true) 
java.sql.Timestamp timestamp; 

只读字段永远不会创建或更新 - 只能在查询中返回。问题是TimeStampType在尝试验证CURRENT_TIMESTAMP()时会引发异常。要解决这一点,你需要定义一个定制的留存:

public class LocalCurrentTimeStampType extends TimeStampType { 
    private static final LocalCurrentTimeStampType singleton = 
     new LocalCurrentTimeStampType(); 
    private String defaultStr; 
    public LocalCurrentTimeStampType() { 
     super(SqlType.DATE, new Class<?>[] { java.sql.Timestamp.class }); 
    } 
    public static LocalCurrentTimeStampType getSingleton() { 
     return singleton; 
    } 
    @Override 
    public boolean isEscapedDefaultValue() { 
     if ("CURRENT_TIMESTAMP()".equals(defaultStr)) { 
      return false; 
     } else { 
      return super.isEscapedDefaultValue(); 
     } 
    } 
    @Override 
    public Object parseDefaultString(FieldType fieldType, String defaultStr) throws SQLException { 
     this.defaultStr = defaultStr; 
     if ("CURRENT_TIMESTAMP()".equals(defaultStr)) { 
      return defaultStr; 
     } else { 
      return super.parseDefaultString(fieldType, defaultStr); 
     } 
    } 
} 

然后你的字段定义变为:

@DatabaseField(persisterClass = LocalCurrentTimeStampType.class, 
    defaultValue = "CURRENT_TIMESTAMP()", readOnly = true) 
java.sql.Timestamp timestamp; 

你可以从GitHub代码的最新版本:https://github.com/j256/ormlite-core

+0

谢谢格雷 - 我理解技术限制,但至少可以节省编辑大量的表。 – Anthony

+0

我在自订表格上使用ORMlite时遇到了奇怪的行为。如果我使用'cdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP'列创建一个表,并且不在对象定义中将其标记为'@DatabaseField(readOnly = true)',即使直接创建表,它也不会设置默认时间戳。执行插入语句时,ORMlite是否显式设置空值? – Phidelux