1

私は Play 2.1.1、Postgress、および Herkou を使用していますが、本番データベースからのみ奇妙な例外が発生します。

ローカル対H2、すべてが機能します。ただし、本番環境では、同じ操作が次のエラーで失敗します。

2013-06-14T01:49:25.275717+00:00 app[web.1]: [←[37minfo←[0m] application - 2013-06-14T01:49:25.275Z - Updating cache with new peak 266
2013-06-14T01:49:48.310600+00:00 app[web.1]: [←[37minfo←[0m] application - Updating database with peak 266
2013-06-14T01:49:48.327490+00:00 app[web.1]: [←[31merror←[0m] application -
2013-06-14T01:49:48.327490+00:00 app[web.1]:
2013-06-14T01:49:48.327490+00:00 app[web.1]: ! @6eih9flgb - Internal server error, for (GET) [/updateDB] ->
2013-06-14T01:49:48.327490+00:00 app[web.1]:
2013-06-14T01:49:48.327490+00:00 app[web.1]: play.api.Application$$anon$1: Execution exception[[RuntimeException: TypeDoesNotMatch(Cannot convert 266:
class java.math.BigDecimal to Long for column ColumnName(peaks.price,Some(price)))]]
2013-06-14T01:49:48.327490+00:00 app[web.1]:    at play.api.Application$class.handleError(Application.scala:289) ~[play_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327490+00:00 app[web.1]:    at play.api.DefaultApplication.handleError(Application.scala:383) [play_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327490+00:00 app[web.1]:    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$12$$anonfun$apply$24.apply(PlayDefaultUp
streamHandler.scala:314) [play_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327490+00:00 app[web.1]:    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$12$$anonfun$apply$24.apply(PlayDefaultUp
streamHandler.scala:312) [play_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327490+00:00 app[web.1]:    at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10-2.1.0.j
ar:2.1.0]
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10-2.1.0.j
ar:2.1.0]
2013-06-14T01:49:48.327660+00:00 app[web.1]: java.lang.RuntimeException: TypeDoesNotMatch(Cannot convert 266:class java.math.BigDecimal to Long for co
lumn ColumnName(peaks.price,Some(price)))
2013-06-14T01:49:48.322664+00:00 heroku[router]: at=info method=GET path=/updateDB host=www.bitcoinpeak.org fwd="84.94.173.221" dyno=web.1 connect=2ms
 service=2019ms status=500 bytes=1941
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at scala.sys.package$.error(package.scala:27) ~[scala-library.jar:na]
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at anorm.Sql$.as(Anorm.scala:535) ~[anorm_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at anorm.Sql$class.executeInsert(Anorm.scala:474) ~[anorm_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at anorm.SimpleSql.executeInsert(Anorm.scala:370) ~[anorm_2.10-2.1.0.jar:2.1.0]
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at org.bitcoinpeak.Peak$$anonfun$addPeak$1.apply(Peak.scala:43) ~[bitcoin-peak_2.10-1.0-SNAPSHOT.jar:1
.0-SNAPSHOT]
2013-06-14T01:49:48.327660+00:00 app[web.1]:    at org.bitcoinpeak.Peak$$anonfun$addPeak$1.apply(Peak.scala:40) ~[bitcoin-peak_2.10-1.0-SNAPSHOT.jar:1
.0-SNAPSHOT]
2013-06-14T01:50:24.933750+00:00 app[web.1]: [←[37minfo←[0m] application - 2013-06-14T01:50:24.933Z - Updating cache with new peak 266
2013-06-14T01:51:24.796588+00:00 app[web.1]: [←[37minfo←[0m] application - 2013-06-14T01:51:24.796Z - Updating cache with new peak 266
2013-06-14T01:51:40.719105+00:00 heroku[router]: at=info method=HEAD path=/ host=www.bitcoinpeak.org fwd="74.86.158.106" dyno=web.1 connect=1ms servic
e=7ms status=404 bytes=1900
2013-06-14T01:52:25.047381+00:00 app[web.1]: [←[37minfo←[0m] application - 2013-06-14T01:52:25.047Z - Updating cache with new peak 266
2013-06-14T01:52:33.646553+00:00 heroku[router]: at=info method=GET path=/ host=www.bitcoinpeak.org fwd="74.86.158.107" dyno=web.1 connect=2ms service
=21ms status=200 bytes=1892
2013-06-14T01:53:25.420489+00:00 app[web.1]: [←[37minfo←[0m] application - 2013-06-14T01:53:25.420Z - Updating cache with new peak 266  

生産テーブルは次のようになります。

> \d+ Peaks
                                         Table "public.peaks"
 Column |            Type             |       Modifiers        | Storage | Stats target | Description
--------+-----------------------------+------------------------+---------+--------------+-------------
 price  | numeric(20,0)               | not null               | main    |              |
 time   | timestamp without time zone | not null default now() | plain   |              |

ローカルで機能する同じコードが本番環境で失敗するのはなぜですか? SQLフレーバーですか?どうすれば修正できますか?

奇妙な部分は、私が行おうとしているトランザクション (行の挿入) が機能することです。行が追加されます。では、例外はどこから来るのでしょうか?

より多くのコンテキストが必要な場合は、プロジェクト全体が 1 つの githubになります。

更新: ケース クラス:

import java.math.BigDecimal
import org.joda.time.DateTime

case class Peak(
  time: DateTime,
  price: BigDecimal
)
4

3 に答える 3

1

異なるデータベース システムを使用しているときに、同様の問題が発生しました。したがって、データベースのバージョン、構成、テーブルの DDL、および列が BigDecimal として表示される場合と Long として表示される場合がある微妙な違いに使用される正確な JDBC ドライバーを確認することをお勧めします。

このチケットも見たいかもしれません: http://play.lighthouseapp.com/projects/82401/tickets/243-weird-typedoesnotmatch-exception-in-rc-3-and-final

列の順序と特定のバージョンのプレイに問題があるようです。

于 2013-06-14T06:25:24.723 に答える
0

app/helpers フォルダーに AnormExtension ヘルパーを作成します。それを AnormExtension.scala と呼びます。以下のコード。また、BigDecimal を Long ではなく Double に変換した方がよいでしょう。

参考までに - Scala BigDecimal に変換しようとしていないことに注意してください。Scala BigDecimal は謎です。私はそれを放っておきます。

object AnormExtension {

 implicit def rowToDouble: Column[Double] = Column.nonNull { (value, meta) =>
   val MetaDataItem(qualified, nullable, clazz) = meta
     value match {
       case d: java.math.BigDecimal => Right(d.doubleValue())
       case _ => Left(TypeDoesNotMatch("Cannot convert " + value + ":" + value.asInstanceOf[AnyRef].getClass + " to Double for column " + qualified))
     }
 }
}
于 2014-08-06T05:24:49.423 に答える
0

回答が遅くなって申し訳ありませんが、他の人がこの問題に出くわして SO を検索した場合に備えて返信します。

あなたの場合、JDBC ドライバーによって返されるデータ型はLong、H2 ドライバーを使用する場合はデータ型を返しBigDecimal、Postgres ドライバーを使用する場合はデータ型を返しているようです。この動作は、ドライバーの実装と、データベースが JDBC を使用してデータベースのデータ型を Java 型に変換する方法に依存する場合があります。H2 の場合、それは a でそれを行い、Longあなたは良いです。Postgres の場合、BigDecimal代わりに a を返すことにしました。

このリンクで説明されている根本的な原因は異なりますが、同様の問題があります。Column[BigInt]からへの暗黙的な変換を使用して機能するソリューションが提供されてColumn[Long]いますが、代わりに から に変換しColumn[BigDecimal]ますColumn[Long]

implicit def rowToLong: Column[Long] = Column.nonNull { (value, meta) =>
  val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case int: Int => Right(int: Long)
      case long: Long => Right(long)
      case bd:BigDecimal => Right(bd.longValue())  //Handle BigDecimal correctly
      case _ => Left(TypeDoesNotMatch("Cannot convert " + value + ":" + value.asInstanceOf[AnyRef].getClass + " to Long for column " + qualified))
    }
}

Longこれは、タイプ any BigDecimalLongまたはに変換する必要がありintます。Columnこれは、処理の追加を除いて、Anorm クラスの元の Scala コードとほとんど同じですBigDecimal!

この (拒否された) プル リクエストには、さらに進化した暗黙の変換もあります。これらの追加の暗黙的な変換の動作は不確実であるため、これらの変更は拒否されることに注意してください。修正は、使用されている JDBC ドライバーと、おそらくどのバージョンに依存するかを考慮してください。最も重要なことも、これはデータを変更する魔法の動作です。したがって、残念ながら、ユーザーがこれらの変更の責任を負う必要があります。この修正を慎重に適用し、すべての環境およびデータと適切に相互作用することを確認してください。

于 2014-02-03T23:55:41.123 に答える