2011-03-26 38 views
9

我正在尝试ScalaQuery,它真的很棒。我可以使用Scala类定义数据库表,并轻松查询。我怎么能知道ScalaQuery中是否存在数据库表格

但我想知道,在下面的代码中,如何检查一个表是否存在,所以我不会调用两次“Table.ddl.create”并在运行此程序时得到一个异常?

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 
      } 
     } 
    } 
} 

回答

7

ScalaQuery版本0.9.4包括许多在org.scalaquery.meta包有帮助的SQL元数据封装类,如MTable的:

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

在用于ScalaQuery测试代码,我们可以看到正在使用这些类的示例。具体请参阅org.scalaquery.test.MetaTest。

我写了这个小函数给我一个所有已知表的地图,以表名为键。所以现在,在我创建SQL表之前,我可以检查“if(!tableMap.contains(tableName))”。

+0

感谢这篇文章!这是在游戏中制作异步引导的好方法!框架(http://www.playframework.org/documentation/1.2.4/jobs)。干杯, – egbutter 2012-01-29 16:36:09

1

With java.sql.DatabaseMetaData(Interface)。根据您的数据库,可能会实现更多或更少的功能。

+0

所以我想没有ScalaQuery的方式可以做到这一点? – 2011-03-27 03:30:16

+0

我没有找到任何东西,并从我发现的('用户扩展表[[元组类型]]'),我想,目标是使用早期打字。我看不出你如何能够自己顺利地集成动态定义的表格,但我并没有经常使用反射,所以也许有一种方法,我看不到它。该文档有点精简。有一些'meta'类,但我没有找到如何在wiki或博客中使用它们的示例。 :) – 2011-03-27 11:24:35

+0

我也没有找到任何东西。所以我想这是答案。只需要注意,Session#metaData可以获取当前数据库会话的java.sq.DatabaseMetaData。 – 2011-03-28 02:07:56

2

这里有一个完整的解决方案,检查应用开始使用PostgreSQL的DB的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

这个线程是有点老了,但也许有人会觉得这非常有用。我所有的DAO包括此:

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

谢谢,这太棒了。适用于Slick 2.1.x – Gavin 2014-09-10 18:46:18

0

See also the related discussion here.我个人更喜欢hezamu的建议,并按照以下步骤保持干燥扩展它:

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

然后,你可以创建表,隐式会议:

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

您可以在您的DAO impl中定义以下方法(取自Slick MTable.getTables always fails with Unexpected exception[JdbcSQLException: Invalid value 7 for parameter columnIndex [90008-60]]),该方法可为您提供真假,具体取决于是否存在定义的表在您的分贝:

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 
     } 
     } 

或者,您可以检查是否存在 “GIVENTABLENAME” 或某物的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)")) 
     } 

不要忘记添加

import slick.jdbc.meta._ 

然后调用使用通常的@Inject()方法。使用 play 2.4和play-slick 1.0.0。

干杯,

相关问题