こんにちは私はUnexpectedNullableFoundを取得する問題に遭遇しています。列はnull値を返すかもしれませんが、これをOption(以下のように)にマッピングしていますので、問題は発生しません。これは私がこのテーブルから取る他のフィールドでも機能します。コードから「pe.company AS admin_company」と関連するマッピングを削除しても、問題はありません。UnexpectedNullableFound left join
admin_companyがnullの場合、この問題が発生します。そうでない場合は、正常に実行されます。
多くの関連する問題を読みましたが、ここでは解決策が見つかりませんでした。
これに関するご意見はありますか?おかげ
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[RuntimeException: ColumnName(test_users.company,Some(admin_company))]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:265)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:191)
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:179)
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:212)
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:94)
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3.applyOrElse(PlayDefaultUpstreamHandler.scala:266)
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3.applyOrElse(PlayDefaultUpstreamHandler.scala:262)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:109)
at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
at scala.concurrent.Promise$class.complete(Promise.scala:55)
at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:23)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
Caused by: java.lang.RuntimeException: ColumnName(test_users.company,Some(admin_company))
at scala.sys.package$.error(package.scala:27)
at anorm.SqlRequestError$class.toFailure(Anorm.scala:20)
at anorm.UnexpectedNullableFound.toFailure(Anorm.scala:37)
at anorm.Sql$$anonfun$asTry$2$$anonfun$apply$7.apply(Anorm.scala:303)
at anorm.Sql$$anonfun$asTry$2$$anonfun$apply$7.apply(Anorm.scala:303)
at anorm.SqlResult$class.fold(SqlResult.scala:23)
at anorm.Error.fold(SqlResult.scala:31)
at anorm.Sql$$anonfun$asTry$2.apply(Anorm.scala:303)
at anorm.Sql$$anonfun$asTry$2.apply(Anorm.scala:303)
at scala.util.Success.flatMap(Try.scala:230)
at anorm.Sql$.asTry(Anorm.scala:303)
at anorm.WithResult$class.as(SqlResult.scala:120)
at anorm.SimpleSql.as(SimpleSql.scala:6)
at com.company.test.user.service.testUserService$$anonfun$findByEmail$1.apply(testUserService.scala:229)
at com.company.test.user.service.testUserService$$anonfun$findByEmail$1.apply(testUserService.scala:214)
at play.api.db.DefaultDatabase.withConnection(Databases.scala:155)
at play.api.db.DefaultDatabase.withConnection(Databases.scala:149)
at play.api.db.DB$.withConnection(DB.scala:61)
at com.company.test.user.service.testUserService.findByEmail(testUserService.scala:214)
at com.company.test.controllers.testLoginController.checkPasswordAndSaveUserInSession(testLoginController.scala:128)
これは、関連するコードでは:
def findByUserId(userId: Long): TestUser = {
DB.withConnection { implicit connection =>
SQL"""
SELECT s.test_users_id, s.test_users_email AS user_email, s.test_users_first_name, s.test_users_second_name, s.company, s.useas, s.Stripe_CUSTOMER_ID,
s.is_invoice_customer, s.test_users_invoice_email,
s.password_hash, s.salt, s.invoice_address,
s.time_zone, s.last_payment_date AS user_last_payment_date, s.sign_up_date, s.test_role AS user_test_role, s.num_seats, (SELECT COUNT(*) FROM test_users_paid_for WHERE test_users_admin_id = $userId) AS paid_for_seats,
s.syndication_access_manager, p.test_users_admin_id, pe.last_payment_date AS admin_last_payment_date, pe.test_role AS admin_test_role,
s.first_payment_date AS first_payment_date, pe.first_payment_date AS admin_first_payment_date, pe.test_users_email AS admin_email, pe.company AS admin_company, s.utm_source, s.utm_medium, s.utm_campaign, s.sf_exec, s.bounced_email,
s.vat_number
FROM test_users AS s
LEFT JOIN test_users_paid_for AS p ON email_users_email = s.test_users_email
LEFT JOIN test_users AS pe ON p.test_users_admin_id = pe.test_users_id
WHERE s.test_users_id = $userId
""".as(simple.single)
}
}
val customer = {
get[Long]("test_users_id") ~
get[Option[Long]]("test_users_admin_id") ~
get[String]("company") ~
getAliased[Option[String]]("admin_company") ~
getAliased[Option[DateTime]]("first_payment_date") ~
getAliased[Option[DateTime]]("admin_first_payment_date") ~
getAliased[Option[String]]("user_test_role") ~
getAliased[Option[String]]("admin_test_role") map {
case testUserId ~ testUsersAdminId ~ company ~ adminCompany ~ firstPaymentDate ~ adminFirstPaymentDate ~ testRole ~ admintestRole =>
if(testUsersAdminId.isDefined){
getCompanyCustomer(testUsersAdminId, adminCompany, adminFirstPaymentDate, admintestRole)
} else {
getCompanyCustomer(Some(testUserId), Some(company), firstPaymentDate, testRole)
}
}
}
def getCompanyCustomer(testUsersAdminId: Option[Long], adminCompany: Option[String], adminFirstPaymentDate: Option[DateTime], admintestRole: Option[String]): Option[CompanyCustomer] = {
for {
id <- testUsersAdminId
company <- adminCompany
firstPaymentDate <- adminFirstPaymentDate
testRole <- admintestRole
} yield CompanyCustomer(id, company, firstPaymentDate, testRole)
}
val simple = {
get[Long]("test_users_id") ~
getAliased[String]("user_email") ~
get[String]("test_users_first_name") ~
get[String]("test_users_second_name") ~
get[String]("company") ~
customer ~
get[String]("useas") ~
get[Option[String]]("Stripe_CUSTOMER_ID") ~
get[Boolean]("is_invoice_customer") ~
get[Option[String]]("test_users_invoice_email") ~
get[Array[Byte]]("password_hash") ~
get[Array[Byte]]("salt") ~
get[String]("invoice_address") ~
get[Option[String]]("time_zone") ~
getAliased[DateTime]("user_last_payment_date") ~
get[DateTime]("sign_up_date") ~
getAliased[Option[String]]("user_test_role") ~
get[Option[Int]]("num_team") ~
get[Int]("paid_for_team") ~
get[Option[Long]]("test_users_admin_id") ~
getAliased[Option[DateTime]]("admin_last_payment_date") ~
getAliased[Option[String]]("admin_test_role") ~
getAliased[Option[DateTime]]("first_payment_date") ~
getAliased[Option[String]]("admin_email") ~
getAliased[Option[DateTime]]("admin_first_payment_date") ~
getAliased[Option[String]]("utm_source") ~
getAliased[Option[String]]("utm_medium") ~
getAliased[Option[String]]("utm_campaign") ~
getAliased[Option[String]]("sf_exec") ~
get[Option[Long]]("access_manager") ~
get[Option[String]]("vat_number") ~
getAliased[Boolean]("bounced_email") map {
case testUsersId ~ userEmail ~ testUsersFirstName ~ testUsersSecondName
~ company ~ adminCustomer ~ useAs ~ stripeCustomerId ~ isInvoiceCustomer ~ secondContactEmail ~ passwordHash ~ salt ~
invoiceAddress ~ timeZone ~ lastPaymentDate ~ signUpDate ~ testRole ~ numteam ~ paidForteam ~ testUsersAdminId ~ adminLastPaymentDate ~ admintestRole ~ firstPaymentDate ~
adminEmail ~ adminFirstPaymentDate ~ utmSource ~ utmMedium ~ utmCampaign ~ sfExec ~ syndicationAccessManagerId ~ vatNumber ~ bouncedEmail =>
testUser(testUsersId, userEmail, testUsersFirstName,
testUsersSecondName, company, adminCustomer, useAs, invoiceAddress,
stripeCustomerId,
isInvoiceCustomer,
secondContactEmail,
passwordHash.toVector, salt.toVector,
teamLastPaymentDate(lastPaymentDate, adminLastPaymentDate, testUsersAdminId, stripeCustomerId), new DateTime(signUpDate, DateTimeZone.UTC),
testRoleFromTeam(testRole, testUsersAdminId, stripeCustomerId, admintestRole), paidByOtherUser(testUsersAdminId, stripeCustomerId), numteam.getOrElse[Int](0), //
getSeatCount(paidForteam), timeZone.flatMap(getSafeTimeZone),
firstPaymentDateFromTeam(testUsersAdminId, stripeCustomerId, firstPaymentDate, adminFirstPaymentDate), adminEmail, utmSource, utmMedium, utmCampaign,
sfExec, syndicationAccessManagerId, vatNumber, bouncedEmail)
}
}
投影には2つの 'company'カラムがあります(' s'、 'pe')。この場合はエイリアスのみを使用してください。 P.S: 'getAlias'は推奨されていません。 – cchantep
@cchantepわれわれはAnorm 2.4.0を1分で稼働させているが、getAliased 2.5で問題があり、私たちのアップグレードを妨げている。私たちは2.6がリリースされるのを待っているので、今はgetAliasedを使用して立ち往生しています。 2.6がリリースされる見込みはいつですか? – smur89
'getAliased'はもう使用しないでください – cchantep