如何在应用程序启动时连接到Cassandra

如何在应用程序启动时连接到Cassandra,cassandra,datastax,playframework-2.6,Cassandra,Datastax,Playframework 2.6,我有一个Play应用程序需要连接到Cassandra。我正在使用Datastax的驱动程序连接到Cassandra 我能够从控制器连接到数据库。代码片段是(完整代码来自 我在控制器中使用上述代码,如下所示: class UserController @Inject()(cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc){ def addUser = Action.

我有一个
Play
应用程序需要连接到
Cassandra
。我正在使用Datastax的驱动程序连接到Cassandra

我能够从控制器连接到数据库。代码片段是(完整代码来自

我在控制器中使用上述代码,如下所示:

class UserController @Inject()(cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc){

  def addUser = Action.async{ implicit request => {
    println("addUser controller called")
    println("testing database connection")

    val uri = CassandraConnectionUri("cassandra://localhost:9042/killrvideo")
    println(s"got uri object ${uri.host}, ${uri.hosts}, ${uri.port}, ${uri.keyspace}")
    val session = Helper.createSessionAndInitKeyspace(uri)

    val resultSet = session.execute(s"select * from users")
    val row = resultSet.one()
    println("got row ",row)
    val user = User(UUID.randomUUID(),UserProfile(true,Some("m@m.com"),Some("m"),Some("c")))
...
  }

虽然代码可以工作,但我想我不应该从控制器内连接到数据库。我应该在
play
应用程序启动时连接到数据库,并将连接注入控制器。但我不知道如何做。这是在
play
中创建数据库应用程序的正确方法吗?

简短描述:

从控制器类连接C*不是一种好做法。建议在访问DB时使用单独的存储库/存储类。您将创建一个DB访问类,并将该类注入控制器类的构造函数。 这是我创建自己的Cassandra应用程序所遵循的开源示例应用程序。您可以遵循此项目

详细描述:

以下是一些基本的概念:

第1步: 在application.conf文件中定义数据库配置:

db {
      keyspace = "persons"
      table = "person_info"
      preparedStatementCacheSize = 100
      session {
        contactPoints = ["127.0.0.1"]
        queryOptions {
          consistencyLevel = "LOCAL_QUORUM"
        }
      }
    }
第2步:创建一个Singleton类来主控与Cassandra DB的连接

class CassandraConnectionProvider @Inject()(config: Configuration) extends Provider[CassandraConnection] {
  override def get(): CassandraConnection = {
    val hosts = config.getStringList("db.session.contactPoints")
    val keyspace = config.getString("db.keyspace")

    // Use the Cluster Builder if you need to add username/password and handle SSL or tweak the connection
    ContactPoints(hosts.asScala).keySpace(keyspace)
  }
}
第3步:现在创建一个存储库类,您可以在其中对数据库执行
CRUD
操作

class PhantomPersonRepository @Inject()(config: Configuration, connection: CassandraConnection, ec: ExecutionContext)
  extends CassandraTable[PhantomPersonRepository, Person] with PersonRepository[Future] {
  // See https://github.com/outworkers/phantom/wiki/Using-the-Database-class-and-understanding-connectors
  implicit val session: Session = connection.session
  implicit val keySpace: KeySpace = connection.provider.space
  override val tableName: String = config.getString("db.table").getOrElse("person_info")
  implicit val executionContext: ExecutionContext = ec

  object id extends UUIDColumn(this) with PartitionKey

  object firstName extends StringColumn(this) {
    override def name: String = "first_name"
  }

  object lastName extends StringColumn(this) {
    override def name: String = "last_name"
  }

  object studentId extends StringColumn(this) {
    override def name: String = "student_id"
  }

  object gender extends EnumColumn[Gender.Value](this)

  override implicit val monad: Monad[Future] = cats.instances.future.catsStdInstancesForFuture

  override def create(person: Person): Future[Person] =
    insert.value(_.id, person.id)
      .value(_.firstName, person.firstName)
      .value(_.lastName, person.lastName)
      .value(_.studentId, person.studentId)
      .value(_.gender, person.gender)
      .consistencyLevel_=(ConsistencyLevel.LOCAL_QUORUM)
      .future()
      .map(_ => person)

  // https://github.com/outworkers/phantom/wiki/Querying#query-api
  override def find(personId: UUID): Future[Option[Person]] =
    select.where(_.id eqs personId)
      .consistencyLevel_=(ConsistencyLevel.LOCAL_QUORUM)
      .one()

  override def update(person: Person): Future[Person] = create(person)
.....
步骤4:现在将此存储库类注入控制器类并访问数据库:

@Singleton
class PersonController @Inject()(personRepo: PersonRepository[Future])(implicit ec: ExecutionContext) extends Controller {

  def create: Action[JsValue] = Action.async(parse.json) { request =>
    onValidationSuccess[CreatePerson](request.body) { createPerson =>
      val person = Person(UUID.nameUUIDFromBytes(createPerson.studentId.getBytes()), createPerson.firstName,
        createPerson.lastName, createPerson.studentId, createPerson.gender.toModel)
      personRepo.find(person.id).flatMap {
        case None => personRepo.create(person).map(createdPerson => Created(createdPerson.toJson))
        case Some(existing) => Future.successful(Conflict(existing.toJson))
      }.recover { case _ => ServiceUnavailable }
    }
  } 
 .....
希望这对你有帮助。所有代码都要归功于

@Singleton
class PersonController @Inject()(personRepo: PersonRepository[Future])(implicit ec: ExecutionContext) extends Controller {

  def create: Action[JsValue] = Action.async(parse.json) { request =>
    onValidationSuccess[CreatePerson](request.body) { createPerson =>
      val person = Person(UUID.nameUUIDFromBytes(createPerson.studentId.getBytes()), createPerson.firstName,
        createPerson.lastName, createPerson.studentId, createPerson.gender.toModel)
      personRepo.find(person.id).flatMap {
        case None => personRepo.create(person).map(createdPerson => Created(createdPerson.toJson))
        case Some(existing) => Future.successful(Conflict(existing.toJson))
      }.recover { case _ => ServiceUnavailable }
    }
  } 
 .....