【问题标题】:Is it Java best practice to store dates as longs in your database?将日期存储在数据库中是 Java 的最佳实践吗?
【发布时间】:2012-10-29 12:19:15
【问题描述】:

我这样做的原因是,在任何数据库中存储为日期对象的日期往往以特定格式编写,这可能与您需要在前端呈现给用户的内容大不相同。我还认为,如果您的应用程序从不同类型的数据存储中提取信息,这将特别有用。一个很好的例子是 MongoDB 和 SQL 日期对象之间的区别。

但是,我不知道这是否是推荐的做法。我应该继续将日期存储为 long(以毫秒为单位的时间)还是日期对象?

【问题讨论】:

  • 答案是.....取决于。
  • 是的,这取决于您是否使用检索到的日期
  • 只有当它是你的数据库时,任何人都不会以任何理由接触。 (哈哈)一旦用户掌握它并想写一些报告,您就会收到一些紧急且措辞强硬的变更单!
  • 这在很大程度上取决于您的数据库是否需要将日期理解为日期。

标签: java sql mongodb date timestamp


【解决方案1】:

关于 MongoDB,我不能代表它,但在 SQL 数据库中,不,这不是最佳实践。这并不意味着可能没有偶尔的用例,而是“最佳实践”没有。

将它们存储为日期,将它们检索为日期。您最好的选择是设置您的数据库以将它们存储为 UTC(松散地,“GMT”),以便数据是可移植的,并且您可以根据需要使用不同的本地时间(例如,如果数据库由地理上不同的用户使用) ,并在应用层处理从 UTC 到本地时间的任何转换(例如,通过Calendar 或第三方日期库)。

将日期存储为数字意味着您的数据库难以报告、运行临时查询等。我犯过一次错误,如果没有真正充分的理由,我不会重复. :-)

【讨论】:

  • +1 在内部,大多数数据库将数据存储为 long 或 ints 的日期/时间字段,而不是特定的文本格式(因此在 SQL 中使用 DATE 不会丢失任何内容)但是什么您获得的是数据库知道它的日期并显示它,它可以以友好的格式进行查询。
  • +1 和另一个用于提及时区。如果您允许每个用户解释他自己时区中的毫秒数,那么手动更正偏移量是一种痛苦...
  • @Andreas_D:确实——但这是我使用“本机”数据库日期/时间类型的主要问题;通常不清楚时区转换是否以及在何处发生。大多数客户端 API(例如 JDBC)在整个事情上都非常模糊,这无济于事:(
  • @JonSkeet:这就是您将数据库设置为 UTC 的原因。所以很清楚。在 MySQL 上,它是 default-time-zone 选项。令人震惊的是,SQL Server 似乎让这变得更加困难。
  • @T.J.Crowder:但是您必须担心客户端代码可能会执行您不希望的转换。我的经验是,这类事情真的记录得很糟糕。
【解决方案2】:

这很大程度上取决于:

  • 您使用的数据库及其日期/时间支持
  • 您的客户需求(例如,您对自己始终使用 Java 的想法感到高兴)
  • 您真正想要表达的信息是什么
  • 您的诊断工具

第三点可能是最重要的。想想你试图存储的值的真正含义。即使您显然没有使用 Noda Time,但希望我的 user guide page on choosing which Noda Time type to use 基于您的输入数据可以帮助您清楚地考虑这一点。

如果曾经使用过 Java,并且您的数据库对日期/时间类型没有非常好的支持,而您只是试图表示一个“即时”(而不是说,特定时区的瞬间,或带有偏移量的本地日期/时间,或只是本地日期/时间,或只是一个日期......),而你'重新编写诊断工具以将您的数据转换为更易于阅读的形式 - 然后存储 long 是合理的。但这是一个相当长的“如果”列表。

如果您希望能够在数据库中执行日期操作 - 例如询问在该月的第一天发生的所有值 - 那么您可能应该使用日期/时间类型,注意时区。 (我的经验是,当涉及到日期/时间类型时,大多数数据库的文档记录至少令人震惊。)

一般来说,您应该使用能够满足您所有要求并且是该特定环境最自然表示的任何类型。因此,在具有日期/时间类型的数据库中,当您与之交互时不会给您带来问题(例如,以未经请求的方式执行任意时区转换),请使用该类型。它会让各种事情变得更容易。

使用更“原始”的表示(例如 64 位整数)的优势恰恰是数据库不会弄乱它。您实际上是从数据库中隐藏了数据的含义,具有该方法的所有正常优点和缺点(主要是缺点)。

【讨论】:

  • 为什么要写节点时间?还有约达时间。语言支持不够?
  • @DarthVader:Noda Time 是 Joda Time 引擎到 .NET 的一个端口。 .NET API 严重不足 IMO。
【解决方案3】:

我不认为将日期存储的时间越长越好,因为这意味着您将无法执行任何特定于日期的查询。喜欢:

where date between 

我们也无法轻松地使用 sql 查询从表中获取日期月份。

最好在 java 层中使用单一的日期格式转换器,并将日期转换为该格式,并在整个应用程序中使用单一格式。

【讨论】:

  • 您也只需要将查询转换为长日期。
【解决方案4】:

恕我直言,如果您可以使用字符串,最好将日期存储在数据库中。因此,如果您不需要日历中的所有字段,请避免不必要的数据上下传输到服务器。 日历中有很多数据,每个日历实例也很重。

因此,将其存储为 String ,仅包含所需的数据,然后在需要时将其转换回 Calendar 并使用它们。

【讨论】:

  • 如果您不需要 Calendar 对象中的所有内容,或者您​​只需要 dd/mm/yyyy ,为什么这不是一个好主意?
  • 根本不是一个好主意,例如:您将如何进行查询以检索 20/09/2002 和 20/09/2010 之间的数据
  • String 几乎是最糟糕的表现形式,IMO。它在任何地方都涉及潜在的错误和繁琐的转换,如果您想要求数据库解释值,它的效率很低,而且它不是客户端或数据库的“本机”表示。
  • @SubinS:完全可以使用可排序的 sensible 字符串表示 - 这将启用“介于”查询,但总的来说这仍然是一个坏主意。跨度>
【解决方案5】:

这取决于各个方面。当使用标准的“自纪元以来的秒数”时,如果有人只使用整数精度,他们的日期被限制在 1970-2038 年的范围内。

但也存在一些精度问题。例如,unix 时间忽略闰秒。每天被定义为具有相同的秒数。因此,当计算 unix 时间之间的时间增量时,您确实会遇到一些错误。

但更重要的是,您假设您的所有日期都是完全已知的,因为您的陈述不可能仅将指定日期的一半减半。在现实中,有很多你不知道秒(甚至毫秒)精度的事件。因此,如果表示允许指定例如,它是一个特征。只有 精度。理想情况下,您可以存储日期及其精确信息。

此外,假设您正在构建一个日历应用程序。有时间,但也有当地时间。很多时候,您需要两个可用的信息。当调度重叠时,你当然可以在同步的时间内做到最好,所以这里的 long 会很好。但是,如果您还想确保不会在当地时间 9-20 小时之外安排活动,则还需要始终保留时区信息。对于跨越多个位置的任何事情,您确实需要在日期表示中包含时区。假设您可以将您看到的所有日期转换为您当前的本地时间是非常幼稚的。

请注意,SQL 中的日期可能会导致奇怪的情况。我最喜欢的一个是以下 MySQL 荒谬

SELECT * FROM Dates WHERE date IS NULL AND date IS NOT NULL;

可能返回日期为 0000-00-00 00:00:00 的记录,尽管这违反了对逻辑的普遍理解。

【讨论】:

    【解决方案6】:

    由于这个问题被标记为 MongoDB:MongoDB 不会将日期存储在 String 或其他类型中,它们实际上将其存储为 long (http://www.mongodb.org/display/DOCS/Dates):

    BSON 日期值将自 Unix 纪元(1970 年 1 月 1 日)以来的毫秒数存储为 64 位整数。 v2.0+ :此数字已签名,因此 1970 年之前的日期存储为负数。

    由于 MongoDB 没有立即计划使用 SQL 在标准查询中具有的复杂日期处理功能(例如仅查询年份等),因此没有真正的缺点,它实际上可能会减少索引和存储的大小。

    这里需要考虑一件事,聚合框架:http://docs.mongodb.org/manual/reference/aggregation/#date-operators 只有在 MongoDB 中支持的 BSON 日期类型才能实现奇怪而美妙的事情,但是,这对您是否重要取决于您的查询。

    您认为自己需要聚合框架功能吗?或者在头顶放置额外的对象会很痛苦?

    我个人的看法是,BSON 日期类型是一个如此小的对象,如果没有它来存储文档,将会无缘无故地影响整个系统及其未来的兼容性。所以,是的,我会使用 BSON 日期类型而不是 long,我认为这样做是一种好习惯。

    【讨论】:

      猜你喜欢
      • 2010-11-10
      • 1970-01-01
      • 2018-08-13
      • 2011-03-23
      • 2011-03-31
      • 2018-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多