2015-10-12 17 views
6

私はScalaSlickおよびPostgresを使ってアプリケーションを構築しています。私は滑らかなテーブルを生成するためにSlick code generatorを使用しました。データベースのスキーマを既存の滑らかなテーブルと比較する

私は、データベーステーブルスキーマと滑らかなテーブルスキーマが一致していることを確認する方法があるかどうかを知りたいと思っています。例えば

class DepartmentTable(_tableTag: Tag) extends Table[Department](_tableTag, Some("base"), "Department") { 
    val id: Rep[Long] = column[Long]("DepartmentId", O.AutoInc, O.PrimaryKey) 
    val name: Rep[String] = column[String]("Name", O.Length(50,varying=true)) 
    val shortCode: Rep[String] = column[String]("ShortCode", O.Length(50,varying=true)) 
    def * = ??? 
    def ? = ??? 
} 

Iは、データベーステーブルを変更表に列parentDepartmentIdを追加言うし、次いでスリックテーブルにそれを添加しました。多くの場合、変更スクリプトがテストデータベース上で実行されないため、実行時例外が発生するという問題がありました。

このような問題を回避するために、滑らかなテーブルが実際のpostgresテーブルと一致するかどうかを確認するために何かを実装しようとしていました。それは達成可能ですか?

私は反射を試みましたが、滑らかなテーブルからすべての詳細を得ることはできませんでした。例:実際の列名

Slick Version : 3.0 

達成しようとしていることはありますか?

アプリケーションの起動時に、データベーススキーマと滑らかなスキーマを比較する必要があります。

私の計画:

  1. は自分のアプリケーションからすべてのTableQuery /スリックテーブルを取得します

  2. スリックメタ

  3. が持つ滑らかなtablequery構造の比較使用して実際のデータベーススキーマを取得します。実際のデータベース

マキシムが提案したように、私はレジストリを作成し、各テーブルをレジストリに追加することができます。他の方法があるかどうかを確認したいだけです。その理由は、私または他の人が、誤って2つのテーブルクエリをレジストリに追加することを削除した場合、そのテーブルのチェックは行われないということです。私はもっ​​と安全にしようとしていますが、そのような方法が存在するかどうかはわかりません。

+0

Slickの 'Table' **クラス**とテーブルの**構造**と** Slickの' TableQuery'クラスの**インスタンス**を混同しないようにしてください。 Slickの実際のデータベース**テーブル** –

答えて

0

ここでは、指定されたSlickテーブルに対して、テーブルに対応すると思われるデータベーススキーマ内のすべての列の数、名前、およびSQLタイプが、数値、名前、SQLタイプと等しいかどうかを検出する方法の例を示します。テーブルのスリック表記述の列

def ?[AT <: AbstractTable[_]](tableQuery: profile.api.TableQuery[AT]) 
          (implicit ec: ExecutionContext) = { 
    val table = tableQuery.baseTableRow.create_*.map(c => 
    (c.name, profile.jdbcTypeFor(c.tpe).sqlType)).toSeq.sortBy(_._1) 
    MTable.getTables(tableQuery.baseTableRow.tableName).headOption.map(
    _.map{_.getColumns.map(
     _.sortBy(_.name).map(c => (c.name, c.sqlType)) == table 
    )} 
) flatMap (_.head) 
} 

ます。また、インデックス、主キーと外部キーがある程度一致するかどうかを検出することができます。私は抜粋でtableQuery.baseTableRow.create_*getColumnsでやったように、そのためにあなたはそれに対応しMTable

getIndexInfo  
getPrimaryKeys 
getImportedKeys 

の次の方法で

tableQuery.baseTableRow.indexes  
tableQuery.baseTableRow.primaryKeys 
tableQuery.baseTableRow.foreignKeys 

を組み合わせることができます。

これで、コード内のすべてのテーブルを簡単に確認できます。唯一本当に簡単な質問は、リストを取得する方法です。真実を伝えるためには、どうすれば問題になるのか理解できません。コードで作成されるたびにテーブルを登録できる集中レジストリを維持することの問題であり、照会することができますオブジェクトは保存されます。あなたは、あなたのワークフローが

val departmentTable = TableQuery[DepartmentTable] 
regsitry.enlistTable(departmentTable) 
... 
val someTable = TableQuery[SomeTableStructureClass] 
regsitry.enlistTable(someTable) 
... 
val anotherTable = TableQuery[AnotherTableStructureClass] 
regsitry.enlistTable(anotherTable) 
... 
for(table <- regsitry.listTables) 
    db run ?(table) map (columnsAndTypesAreIdentical => ...) 
... 

ようになりますこのような方法enlistTableregistrylistTablesを持っているとしましょう。

デフォルトで"generates Table classes, corresponding TableQuery values,..., as well as case classes for holding complete rows of values"を使用したSlickコードジェネレータ。 対応するTableQueryの値の形式は、正確にはval someTable = TableQuery[SomeTableStructureClass]です。

+0

ありがとうございます。私はこれを得ることができます。しかし、問題は、すべてが滑らかな表であるかどうか分からないため、私はTableQuery [部]を行うことができないということです。私は自分のアプリケーション内のすべてのSlickテーブルに対してそのTableQueryを取得できるはずです。しかし私はそれをすることができません。反射の少しを試みたが、まだ同じです。 –

+0

反射?あなたは冗談かもしれない。レジストリ/レポジトリのパターンが使用されるように、あなたのコードを考慮する必要があります。 –

+0

私のコードには100個の滑らかなテーブルがあります。これらの100個のテーブルに対して、どのように 'TableQuery [MyTable1]'を動的に取得できますか? –

3

これを実現するにはslick.metaを使用できます。あなたは使用しているスリックのバージョンを言っていないので、slick 3.0を使用した例を示しますが、DBIOをslick 2.xで古いwithSession APIに置き換えて参照を削除すると、 ExecutionContextおよびFuture

val db: Database = ??? 

val tablesWithCols = for { 
    tables <- slick.jdbc.meta.MTable.getTables 
    withCols <- DBIO.sequence(tables.map(t => t.getColumns.map((t, _)))) 
} yield withCols 

val printLines: DBIO[Seq[String]] = tablesWithCols.map { 
    _.map { 
    case (t, cs) => s"Table: ${t.name.name} - columns: ${cs.map(_.name).mkString(", ")}" 
    } 
} 

val res: Future[Seq[String]] = db.run(printLines) 

res.foreach(println) 

:ここ

は、それはあなたがYourDriver.api._をインポートすることを、スキーマ内のすべての表では、暗黙のExecutionContextスコープで持っていると仮定して、すべての列を印刷して、実際のDatabaseインスタンスで???を置き換えることができる方法でありますまた、最後のforeach呼び出しがFutureで実行されないように、将来完了するか、関連する計算と連鎖することを望むかもしれません。あなたのプログラムが待機/連鎖せずに終了した場合は、そこから何も見えないでしょう。

驚いたことに、やや複雑な問題が、滑らかなテーブル定義から情報を取り込んでいます。私はそれを行うに見つけた唯一の方法は、このようなものです:あなたがあなたが必要とする定義を出すために横断できるAST状の構造を与える

TableQuery[YourTable].toNode.getDumpInfo 
。構造自体はトラバースするのが楽しいものではありませんが、必要なものすべてを含んでいる必要があります。

この問題を回避するために探索できるもう1つのアプローチは、滑らかな定義の生成を包み込み、関連性の高いメタデータをよりアクセス可能な方法で公開することです。しかし、これがあなたをより大きなトラブルに陥らせないかどうかは分かりません。

+0

このようにして、データベースから実際のスキーマの詳細を取得できます。私はすでにやっている。しかし、私が知らないことは、既に自分のコードにあるSlick Tablesを入手する方法です。私は自分のコード内に既に存在するテーブルとMTableを比較する必要があります。 –

+0

私は、滑らかな定義からデータを取得することについて少し追加して回答を拡大しました。申し訳ありませんが、始めに質問を理解できなかった場合。 –

関連する問題