Play 2.6.x 连接MySQL (for Scala)如何使用Object直接获取数据库对象?

分享 未结
0 0 5 18
意式Espresso 2018-03-21发布
收藏 点赞

官方网站连接MySQL的简单示例

package controllers
import javax.inject.Inject

import play.api.db._
import play.api.mvc._

class ScalaControllerInject @Inject()(db: Database, val controllerComponents: ControllerComponents) extends BaseController {

  def index = Action {
    var outString = "Number is "
    val conn = db.getConnection()
    
    try {
      val stmt = conn.createStatement
      val rs = stmt.executeQuery("SELECT 9 as testkey ")
      
      while (rs.next()) {
        outString += rs.getString("testkey")
      }
    } finally {
      conn.close()
    }
    Ok(outString)
  }

}

网上找到的大部分文章都是说直接通过play.api.db.DB来获取数据库操作对象的,但目前的版本好像去掉这一调用方式了,官网的话目前版本是依赖注入的方法,问题是我现在想在Object中获取Database,可是Object又不能用依赖注入,头一次发现哈。

于是查找到了下面这种方法:

import scala.slick.jdbc.JdbcBackend.Database
import play.api.Play.current

object DataSource  {

  //init configuration fromn application.conf
  private val conf = current.configuration
  private val dbUrl = conf.getString("db.default.url").getOrElse("")
  private val user = conf.getString("db.default.user").getOrElse("root")
  private val pwd = conf.getString("db.default.password").getOrElse("root")
  private val driverClass = conf.getString("db.default.driver").getOrElse("com.mysql.jdbc.Driver")

  //create the database instance with configuration
  val database = Database.forURL(dbUrl, user, pwd, driver = driverClass)
}

但是要重新获取配置参数,感觉在application.conf中白配置了,所以说可以在Object中直接获取到Database吗?然后我就可以使用Object的方式四处方便的获取数据库连接了。


回帖
  • 2018-03-21

    在Object中保存Database引用虽然用起来很方便,但是这种方式是不推荐的,因为会导致难以测试的代码。但是不管怎么说,目前借助已被弃用的play.api.Play.current仍然可以实现你需要的功能。但需要注意的是,使用play.api.Play.current进行依赖查找时一定要使用lazy关键字,这是因为Play.current的初始化被安排在所有组件之后,也就是说所有组件均是Play.current的依赖,只有当所有依赖初始化成功后,才能成功创建Play.current实例。示例代码如下:

    object Application {
      lazy val db= play.api.Play.current.injector.instanceOf(classOf[Database])
    }
    

    推荐的做法是使用单例模式,示例代码如下:

    @Singleton
    class Application @Inject()(db: Database)
    



    2
  • 感谢小编的及时解答

    0
  • 依赖注入的方法确实也挺方便的,但还是想试试第一种方法,但失败了,我在Controller中的Action直接使用通过Object调database,但是还是失败了,不过我把错误贴出来吧

    首先我是这么用的:

    import play.api.db.Database
    object DatabaseSimple{
      lazy val db = play.api.Play.current.injector.instanceOf(classOf[Database])
    }
    

    然后:

    package controllers
    
    import javax.inject._
    import models.Modules.Account
    import play.api.libs.json.Json
    import play.api.mvc._
    import service.DatabaseSimple
    
    import scala.collection.mutable.ArrayBuffer
    @Singleton
    class AccountSimpleController @Inject()(cc: ControllerComponents) extends AbstractController(cc){
      implicit val AccountFormat = Json.format[Account]
      /*****************调用区域*********************/
      val db = DatabaseSimple.db
      /*********************************************/
      def listAll = Action {
        implicit request =>
          val array = new ArrayBuffer[Account]()
          db.withConnection{
            conn=>
              val stmt = conn.createStatement()
              val sql = "select * from T_ACCOUNT"
              val rs = stmt.executeQuery(sql)
              while (rs.next()){
                val id = rs.getInt(1)
                val name = rs.getString(2)
                val pwd = rs.getString(3)
                val isadmin = rs.getBoolean(4)
                val newAccount = Account(id, name, pwd, isadmin)
                array.append(newAccount)
              }
          }
    
          val json = Json.toJson(array.toList)
          array.clear()
          Ok(json).as("application/json")
      }
    }
    

    再一次感谢小编的热情解答,真心希望社区热闹起来哈

    代码demo参考自:http://blog.csdn.net/zl3450341/article/details/38538023

    0
  • 2018-03-22

    @意式Espresso  调用DatabaseSimple.db的代码不能放在类初始化区域,这样lazy就失去意义了,可以使用def或再次使用lazy:

    /*****************调用区域*********************/
    def db = DatabaseSimple.db
    或
    lazy val db = DatabaseSimple.db
    


    0
  • OK,可以用了,谢谢小编哈

    0