从sql获取响应,将其存储在对象中并使用条件?

时间:2017-10-18 03:52:46

标签: mysql sql-server scala playframework

我有两个sql语句要执行并进行有效性检查。我需要的是,我执行第一个查询并将响应存储在一个对象中并检查对象是否为空,如果它不为空,则执行第二个查询。 所以,我尝试过像

这样的东西

在rolerepository.scala =>

  override val allQuery = s"""
    select UserRoles.* from
      (select CASE rbac.roleTypeID
         ELSE rbac.name   JOIN dirNetworkInfo ni
           ON UserRoles.PersonID = ni.PersonID
              where ni.Loginname = {loginName}
                 and UserRoles.roleName in ( 'Business User ','Administrator')"""

(这只是查询的一些示例 - 这里没有完全写出来。) 然后我将它映射到一个模型类写在

之外的对象
   override def map2Object(implicit map: Map[String, Any]): 
     HierarchyEntryBillingRoleCheck = {    
     HierarchyEntryBillingRoleCheck(str("roleName"), oint("PersonID"))  }

然后我编写了getall方法来执行查询

   override def getAll(implicit loginName: String): 
   Future[Seq[HierarchyEntryBillingRoleCheck]] = {
    doQueryIgnoreRowErrors(allQuery, "loginName" -> loginName) }

然后我编写了方法来检查第一个sql的响应是否为空。这是我被困住了,无法继续前进。

    def method1()= {
     val getallresponse = HierarchyEntryBillingRoleCheck 
     getallresponse.toString
     if (getallresponse != " ")
       billingMonthCheckRepository.getrepo()
   }

我在最后一个右大括号中遇到错误(类型不匹配),我不知道这里可以使用哪些其他逻辑。 你们中的任何一个人都可以解释并给我一些解决方案吗?

我也尝试在控制器中使用for循环,但没有得到如何做到这一点。

我试过了 - >

      def getAll(implicit queryParams: QueryParams, 
     billingMonthmodel:Seq[HierarchyEntryBillingRoleCheck]): 
    Action[AnyContent] = securityService.authenticate() { implicit request 
   =>  withErrorRecovery { req =>
    toJson {
      repository.getAll(request.user.loginName)
      for {
      rolenamecheck <- billingMonthmodel

        }yield rolenamecheck
     }}}}

2 个答案:

答案 0 :(得分:1)

哇我不知道这里的格式化是怎么回事,我真的试图在工具栏上使用代码格式化程序,但我不知道为什么它不会格式化,即使多次按下也是如此。我邀请社区编辑我的代码格式,因为我无法弄明白。向OP道歉。

因为我发现如果你不熟悉Play的文档很难跋涉,我不会仅仅留下链接。

  1. 您必须将数据库实例注入控制器。然后,它将作为全局变量提供给您:
  2. @Singleton
     class LoginRegController @Inject()(**myDB: Database**, cc: ControllerComponents ) { 
         //  do stuff
                     }
    

    但是,在控制器中实际使用此连接是不好的做法,因为JDBC是一个阻塞操作,因此您需要创建一个Model,它将db作为方法的参数。不要将对象的构造函数设置为获取DB并将其存储为字段。由于某种原因,这会导致连接泄漏,并且在完成查询后连接将不会释放。不知道为什么,但就是这样。

    1. 创建一个用于执行查询的Model对象。不是通过对象的构造函数传递DB,而是将其传递给您将创建的方法:

      对象DBChecker {       def attemptLogin(db:Database,password:String):String = {

      }}
      
      1. 在您的方法中,使用方法.withConnection { conn =>来访问JDBC连接。所以,像这样:

        对象DBChecker {

        def attemptLogin(db:Database,password:String):String = {         var username:String =“”
        db.withConnection {conn =&gt;

            val query:String = s"SELECT uploaded_by, date_added FROM tableName where PASSWORD = $password ;"
        
          val stmt = conn.createStatement()
        
          val qryResult:ResultSet = stmt.executeQuery(query) 
          // then iterate over your ResultSet to get the results from the query 
          if (qryResult.next()) {
            userName = qryResult.getString("uploaded_by")
        

        }       }   } 返回用户名 }

    2. //请注意,请查看PreparedStatement对象的使用,这样做会让您容易受到SQL注入攻击。

      1. 在Controller中,只要导入对象,就可以从步骤1中创建的控制器中调用该对象的方法。

            import com.path.to.object.DBChecker
        

        @Singleton
        class LoginRegController @Inject()( myDB:Database ,cc:ControllerComponents){def attemptLogin(pass:String)= Action { 隐式请求:请求[AnyContent] =&gt; {         val result:String = DbChecker.attemptLogin(pass)

                // do your work with the results here 
          }
        

答案 1 :(得分:1)

您不会说出您正在使用的数据库访问方法。 (我假设是anorm)。解决这个问题的一种方法是:

  • 创建与您的表匹配的案例类
  • 创建与案例类匹配的解析器
  • 使用Option(或Either)为特定参数集返回一行

例如,也许你有:

case class UserRole (id:Int, loginName:String, roleName:String)

然后

object UserRole {
  val sqlFields = "ur.id, ur.loginName, ur.roleName"
  val userRoleParser = {
    get[Int]("id") ~
    get[String]("loginName") ~
    get[String]("roleName") map {
      case id ~ loginName ~ roleName => {
        UserRole(id, loginName, roleName)
      }
    }
}
...

解析器将行映射到您的case类。下一步是创建单行方法,如findByIdfindByLoginName和多行方法,可能是allForRoleName或其他通用过滤方法。在您的情况下,可能(假设每个loginName有一个角色)类似于:

def findByLoginName(loginName:String):Option[UserRole) = DB.withConnection { implicit c =>
  SQL(s"select $sqlFields from userRoles ur ...")
    .on('loginName -> loginName)
    .as(userRoleParser.singleOpt)
}

.as(parser...是关键。通常,您至少需要:

  • as(parser.singleOpt)返回您的案例类的Option
  • as(parser *)返回您的案例类List(如果登录可能存在多个角色,则您需要此
  • as(scalar[Long].singleOpt)返回Option[Long],方便返回countsexists

然后,为了最终直接回到你的问题,你可以调用你的find方法,如果它返回一些东西,继续第二个方法调用,也许是这样:

val userRole = findByLoginName(loginName)
if (userRole.isDefined)
  billingMonthCheckRepository.getrepo()

或者,更加惯用

findByLoginName(loginName).map { userRole =>
  billingMonthCheckRepository.getrepo()
  ...

我已经看到find方法返回Option,但实际上我们发现返回Either[String,(your case class)]更有用,然后字符串包含失败的原因。 Either很酷。

在我的游戏版本(2​​.3.x)中,上面的导入是:

import play.api.db._
import play.api.Play.current
import anorm._
import anorm.SqlParser._

你将会做很多这样的事情,所以值得找一套适合你的模式。