【问题标题】:Postgresql money (or numeric?) type and its corresponding type in Scala (Java)Postgresql 货币(或数字?)类型及其在 Scala (Java) 中的对应类型
【发布时间】:2014-01-18 12:28:37
【问题描述】:

我在Scala 有一个项目,它使用Postresql。它涉及到Postresql的类型货币。我做了一个研究,发现我应该避免在 Postgresql 中使用money 数据类型,而最好使用NUMERIC

我还在客户端(在 Scala 中)使用BigDecimal。但由于错误,我无法使其工作:

could not find implicit value for parameter extractor: anorm.Column[BigDecimal]
[error]     SqlParser.get[BigDecimal]("due_price") ~

所以问题是:

  1. 我应该在PlayPostgresql 中使用哪些数据类型?
  2. 如果其中之一是BigDecimal,我该如何消除错误?

附:我知道 java.util.Currency,但我不需要它,我只需要 amount 的钱,应该是 BigDecimal

【问题讨论】:

    标签: java postgresql scala playframework-2.2 anorm


    【解决方案1】:

    使用整数类型以美分存储金钱以避免舍入错误和精打细算是很常见的。您可以使用 Int、Long、BigInt - 任何您喜欢的。

    【讨论】:

    • 使用 BigDecimal 不是更好吗?
    • 我想是为了避免溢出,所以最好使用BigInt。 Scalas BigInt 具有与 Postgres bigint 相同的值范围(即精度)。 BigDecimal 仍然让你陷入困境:)
    • 关于 could not find implicit value for parameter extractor 的错误仍然存​​在,但现在是 BigInt。
    【解决方案2】:

    您可以使用 BigDecimal,但这里的问题是您从 Anorm 获得的 BigDecimal 类型是 java.math.BigDecimal,而在您的案例类中,您实际上使用的是 scala.math.BigDecimal。

    要使其正常工作,您可以:

    1) 使用 java.math.BigDecimal 定义您的案例类,并在您的应用程序中使用此类型。

    2) 在您的解析器中在这两者之间进行转换,并将 scala 类型保留在您的应用程序中。这似乎是一个更好的解决方案。我们在生产中使用了这种方法。示例:

    case class ABC (id: Int, price: BigDecimal, decimalPlaces: Int)
    

    你的解析器看起来像:

    val simple = {
      get[Int]("id") ~ get[java.math.BigDecimal]("price") ~ get[Int]("decimalPlaces") map {
      case id ~ price ~ decimalPlaces  => ABC(id, BigDecimal(price), decimalPlaces)
    }
    

    当您需要从 Scala BigDecimal 转换回 Java BigDecimal(用于插入、更新等)时:

    val priceAsJavaBD = priceAsScalaBD.bigDecimal //Returns java.math.BigDecimal
    

    此外,您可以有一个字段(例如 decimalPlaces)来明确定义显示此价格时需要多少小数位。

    【讨论】:

    • 使用 BigDecimal 可能会遇到哪些麻烦?什么是 id 和 decimalPlaces?
    • 您会遇到什么麻烦?我们一直将它用于所有与金钱相关的类型,并且效果很好。 Id 和 decimalPlaces 只是您的案例类可能具有的其他字段的示例,您可以删除它们。或者,您可以使用 decimalPlaces 来明确定义您期望的舍入:例如,如果您有 13.45217676 作为价格并且您的 decimalPlaces 是 3,那么您知道您必须将其四舍五入到 13.452。
    • @Alex 如果您使用多种货币,不同的货币可能需要不同的小数位。看看这个:en.wikipedia.org/wiki/ISO_4217
    • 我说的麻烦是 Aleksey Izmailov 的意思。
    • @Alex 这是一个偏好问题。 Aleksey Izmailov 的建议也很有效,尤其是当您只有一种货币或所有货币都具有相同的小数位数要求时。对于加密货币,您可以添加代码 :-)。
    【解决方案3】:

    您的 Anorm 版本不提供 Column[BigInt] 提取器。您可以将其升级为 master,或者将实际 Column 定义从 master (Column.scala) 复制到您的项目中,以便在编译时可用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-31
      • 2013-03-21
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 2011-07-02
      相关资源
      最近更新 更多