2011-03-26 21 views
9

Estoy probando ScalaQuery, es realmente sorprendente. Pude definir la tabla de la base de datos utilizando la clase Scala y consultarla fácilmente.Cómo podría saber si existe una tabla de base de datos en ScalaQuery

Pero me gustaría saber, en el siguiente código, cómo podría verificar si existe una tabla, así que no llamaré 'Table.ddl.create' dos veces y obtendré una excepción cuando ejecute este programa dos veces ?

object Users extends Table[(Int, String, String)]("Users") { 
    def id = column[Int]("id") 
    def first = column[String]("first") 
    def last = column[String]("last") 
    def * = id ~ first ~ last 
} 

object Main 
{ 
    val database = Database.forURL("jdbc:sqlite:sample.db", driver = "org.sqlite.JDBC") 

    def main(args: Array[String]) { 
     database withSession { 
      // How could I know table Users is alrady in the DB? 
      if (???) { 
       Users.ddl.create 
      } 
     } 
    } 
} 

Respuesta

7

ScalaQuery versión 0.9.4 incluye un número de clases votos envoltura de metadatos SQL en el paquete org.scalaquery.meta, como Mtable:

http://scalaquery.org/doc/api/scalaquery-0.9.4/#org.scalaquery.meta.MTable

En el código de prueba para ScalaQuery, podemos ver ejemplos de estas clases que se utilizan. En particular, vea org.scalaquery.test.MetaTest.

Escribí esta pequeña función para darme un mapa de todas las tablas conocidas, tecleadas por el nombre de la tabla.

import org.scalaquery.meta.{MTable} 
def makeTableMap(dbsess: Session) : Map[String, MTable] = { 
    val tableList = MTable.getTables.list()(dbsess); 
    val tableMap = tableList.map{t => (t.name.name, t)}.toMap; 
    tableMap; 
} 

Así que ahora, antes de crear una tabla SQL, puedo comprobar "if (! TableMap.contains (TABLENAME))".

+0

¡Gracias por esta publicación! ¡Esta es una gran manera de hacer un bootstrap asíncrono en la obra! marco (http://www.playframework.org/documentation/1.2.4/jobs). Cheers, – egbutter

1

Con java.sql.DatabaseMetaData (interfaz). Dependiendo de su base de datos, se pueden implementar más o menos funciones.

+0

Así que supongo que no hay manera de ScalaQuery podría hacer esto? –

+0

No encuentro nada, y por lo que encontré ('El usuario extiende la tabla [(tupla de tipos)]'), supongo, el objetivo es usar el mecanografiado anticipado.No veo cómo puede integrar fácilmente las tablas dinámicas definidas, pero no usé el reflejo a menudo, así que tal vez haya una forma, y ​​simplemente no puedo verlo. La documentación es un poco escasa. Hay algunas clases de 'meta', pero no encontré ejemplos de cómo usarlas en la wiki o el blog. :) –

+0

No encuentro nada tampoco. Así que supongo que esta es la respuesta. Y solo una nota, Session # metaData podría obtener el java.sq.DatabaseMetaData de la sesión actual de la base de datos. –

2

Aquí es una solución completa que comprueba al iniciar la aplicación utilizando un PostGreSQL DB para PlayFramework

import globals.DBGlobal 
import models.UsersTable 
import org.scalaquery.meta.MTable 
import org.scalaquery.session.Session 

import play.api.GlobalSettings 
import play.api.Application 

object Global extends GlobalSettings { 

    override def onStart(app: Application) { 

     DBGlobal.db.withSession { session : Session => 
      import org.scalaquery.session.Database.threadLocalSession 
      import org.scalaquery.ql.extended.PostgresDriver.Implicit._ 
      if (!makeTableMap(session).contains("tableName")) { 
       UsersTable.ddl.create(session) 
      } 
     } 
    } 

    def makeTableMap(dbsess: Session): Map[String, MTable] = { 
     val tableList = MTable.getTables.list()(dbsess) 
     val tableMap = tableList.map { 
     t => (t.name.name, t) 
    }.toMap 
     tableMap 
    } 
} 
7

Este hilo es un poco viejo, pero tal vez alguien se encuentra este útil. Todos mis DAOs incluyen lo siguiente:

def create = db withSession { 
    if (!MTable.getTables.list.exists(_.name.name == MyTable.tableName)) 
     MyTable.ddl.create 
} 
+0

Gracias, esto es genial. Funciona con Slick 2.1.x – Gavin

0

See also the related discussion here. yo personalmente prefiero sugerencia hezamu de extiendo la siguiente manera para mantenerlo seco:

def createIfNotExists(tables: TableQuery[_ <: Table[_]]*)(implicit session: Session) { 
    tables foreach {table => if(MTable.getTables(table.baseTableRow.tableName).list.isEmpty) table.ddl.create} 
} 

A continuación, puede simplemente crear las tablas con la sesión implícita:

db withSession { 
    implicit session => 
    createIfNotExists(table1, table2, ..., tablen) 
} 
0

Puede definir en su DAO impl el siguiente método (tomado de Slick MTable.getTables always fails with Unexpected exception[JdbcSQLException: Invalid value 7 for parameter columnIndex [90008-60]]) que le da un verdadero o falso dependiendo de si existe una tabla definida en su base de datos:

def checkTable() : Boolean = { 
     val action = MTable.getTables 
     val future = db.run(action) 
     val retVal = future map {result => 
      result map {x => x} 
     } 

     val x = Await.result(retVal, Duration.Inf) 

     if (x.length > 0) { 
      true 
     } else { 
      false 
     } 
     } 

O bien, se puede comprobar si algún "GIVENTABLENAME" o algo existe con el método println:

 def printTable() ={ 
      val q = db.run(MTable.getTables) 
      println(Await.result(q, Duration.Inf).toList(0)) //prints first MTable element 
      println(Await.result(q, Duration.Inf).toList(1))//prints second MTable element 
      println(Await.result(q, Duration.Inf).toList.toString.contains("MTable(MQName(public.GIVENTABLENAME_pkey),INDEX,null,None,None,None)")) 
     } 

No se olvide de añadir

import slick.jdbc.meta._ 

a continuación, llamar los métodos desde cualquier lugar con el @Inject() habitual. Utilizando play 2.4 y play-slick 1.0.0.

Cheers,

Cuestiones relacionadas