2016-04-05 43 views
1

こんにちは私は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) 
} 
} 
+0

投影には2つの 'company'カラムがあります(' s'、 'pe')。この場合はエイリアスのみを使用してください。 P.S: 'getAlias'は推奨されていません。 – cchantep

+0

@cchantepわれわれはAnorm 2.4.0を1分で稼働させているが、getAliased 2.5で問題があり、私たちのアップグレードを妨げている。私たちは2.6がリリースされるのを待っているので、今はgetAliasedを使用して立ち往生しています。 2.6がリリースされる見込みはいつですか? – smur89

+0

'getAliased'はもう使用しないでください – cchantep

答えて

2

私の問題を解決するには、ここではアッパーケースにすべてのエイリアスを変更することでした。これで今Anormを使ってうまく動作します。2.4

私の新しいコードは以下の通りですが、リファクタリングも含まれていますが、ほとんど同じです。

val simple = { 
get[Long]("test_users_id") ~ 
    getAliased[String]("USER_EMAIL") ~ 
    get[String]("test_users_first_name") ~ 
    get[String]("test_users_second_name") ~ 
    getAliased[String]("USER_COMPANY") ~ 
    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_SPIKE_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_SPIKE_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]]("syndication_access_manager") ~ 
    get[Option[String]]("vat_number") ~ 
    get[Boolean]("bounced_email") ~ 
    getAliased[Option[String]]("ADMIN_COMPANY") map { 
    case testUsersId ~ userEmail ~ testUsersFirstName ~ testUsersSecondName 
    ~ company ~ useAs ~ stripeCustomerId ~ isInvoiceCustomer ~ xeroContactEmail ~ passwordHash ~ salt ~ 
    invoiceAddress ~ timeZone ~ lastPaymentDate ~ signUpDate ~ testRole ~ numTeam ~ paidForTeam ~ testUsersAdminId ~ adminLastPaymentDate ~ adminTestRole ~ firstPaymentDate ~ 
    adminEmail ~ adminFirstPaymentDate ~ utmSource ~ utmMedium ~ utmCampaign ~ sfExec ~ syndicationAccessManagerId ~ vatNumber ~ bouncedEmail ~ adminCompany => 
    TestUser(testUsersId, userEmail, testUsersFirstName, 
     testUsersSecondName, company, useAs, invoiceAddress, 
     stripeCustomerId, 
     isInvoiceCustomer, 
     xeroContactEmail, 
     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, getCompanyCustomer(testUsersAdminId, adminCompany, adminFirstPaymentDate, adminTestRole, testUsersId, company, firstPaymentDate, testRole), bouncedEmail) 
} 
    } 

    def createCompanyCustomer(testUsersAdminId: Option[Long], adminCompany: Option[String], adminFirstPaymentDate: Option[DateTime], adminTestRole: Option[String]): Option[NewsWhipCustomer] = { 
for { 
    id <- testUsersAdminId 
    company <- adminCompany 
    firstPaymentDate <- adminFirstPaymentDate 
    testRole <- adminTestRole 
} yield NewsWhipCustomer(id, company, firstPaymentDate, testRole) 
} 

def getCompanyCustomer(testUsersAdminId: Option[Long], adminCompany: Option[String], adminFirstPaymentDate: Option[DateTime], adminTestRole: Option[String], testUserId: Long, company: String, firstPaymentDate: Option[DateTime], testRole: Option[String]): Option[NewsWhipCustomer] = { 
if (testUsersAdminId.isDefined) { 
    createCompanyCustomer(testUsersAdminId, adminCompany, adminFirstPaymentDate, adminTestRole) 
} else { 
    createCompanyCustomer(Some(testUserId), Some(company), firstPaymentDate, testRole) 
} 
} 


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 AS USER_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_SPIKE_ROLE, s.num_team, (SELECT COUNT(*) FROM test_users_paid_for WHERE test_users_admin_id = $userId) AS paid_for_team, 
    s.syndication_access_manager, p.test_users_admin_id, pe.last_payment_date AS ADMIN_LAST_PAYMENT_DATE, pe.test_role AS ADMIN_SPIKE_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, s.utm_source, s.utm_medium, s.utm_campaign, s.sf_exec, s.bounced_email, 
    s.vat_number, pe.company AS ADMIN_COMPANY 

    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) 
} 
} 
+0

この作業をしたらAnorm 2.5にアップグレードしようとし、getAliasedを変更しました。この例外が発生しました:例外またはエラーにより実行が中止されました:ColumnName(test_users.test_users_email、Some(USER_EMAIL)) anorm.AnormException:ColumnName(test_users.test_users_email、Some(USER_EMAIL)) – smur89

+0

https://github.com/playframework/anorm/issues/94 – smur89

+0

メタの大文字と小文字はドライバによって選択されます。ドライバが大文字で表記している場合、Anormはそれを変更しません。 – cchantep