31

Python に不慣れな私は、SQLAlchemy を称賛する声をよく耳にします。だから私は理解したい:

  1. jOOQQueryDSLのような「型安全な SQL ビルダー」と比較して何が提供されますか?

  2. Java (または Scala) の世界でそれに近いものはありますか? この点でApache Empire-DBが言及されているのを見たことがあります...

4

5 に答える 5

18

SQLAlchemy の注目すべき点の 1 つは、テーブルをファースト クラス オブジェクトにすることです。したがって、コア API は実際にはテーブル オブジェクトを中心に記述されているため、API は本質的にリレーショナルです。したがって、このレベルでは、たとえ API が OO であっても、それは本質的にテーブル、列、関係、結合、エイリアスなどの RDBMS オブジェクトまたは関数を反映しています。二級扱い。また、SQLAlchemy が本当に優れているのは、このレベルの抽象化により、少し「生の」リレーショナル レベルに降りることができるため、他の ORM が提供するものを見たことがないほどの柔軟性を得ることができるからです。興味深いことに、ORM でクラス継承をモデル化するために必要な基本機能の一部は、このレイヤーで実装されています。結合テーブルの継承http://docs.sqlalchemy.org/en/rel_0_7/orm/inheritance.html#joined-table-inheritance

より頻繁に (少なくとも最近) 使用される API は宣言型 API であり、これは実際にはより多くの OO であり、ビジネス ドメイン内のオブジェクトを上で参照したオブジェクトに (ほとんどの場合透過的に) マップします。ここで ORM 機能が登場します。API は他の ORM API に少し似ており、ドメイン オブジェクトを操作し、これらのアクションが基になるテーブル アクションに直接変換されます。

私の知る限りでは、Scala の ORM は、Java で簡単に利用できるもの (継承など) に追いついています。 22 列の制限などの深刻な問題。(私はコメントを読んだことがありますが、なぜ 22 列以上が必要なのか疑問に思っている人はほとんどいませんでした。少なくとも私の経験では、その倍数が必要な、まれとは言えない状況があります)。

scala の ORM (Java とは異なるフレーバーを取り入れているとしても) は、まだ必要なものに追いついていると思います。SQLAlchemy に関して、Java や Scala で見た SQLAlchemy に相当するものはありますか? 私は見たことがありません。

編集: 追加するのを忘れていたのは、宣言型 API を使用している場合でも、SQLAlchemy を使用すると、基になるオブジェクトに直接アクセスできることです。したがって、「class Foo」が宣言的にマップされている場合、Foo.__table__ は、必要に応じて直接使用できるテーブル オブジェクトです。

于 2012-08-16T07:04:17.390 に答える
10

Squerylは、ライブラリのホームページの「SQLALCHEMY's PHILOSOPHY」で説明されているものと同様の構成可能性を提供します。クエリをクエリできます。

val query = from(table)(t => where(t.a === 1) select(t))
val composed = from(query)(q => where(q.b === 2) select(q))

また、設計哲学のかなりの部分を共有しています。主に、物事が複雑になると、ライブラリは「邪魔にならず」、開発者が自分で調整できるようにする必要があります。Squeryl はオブジェクト マッピングを行いますが、ORM というよりは DSL に近いと考えています。

SQLAlchemy 機能リストを一目見ただけで共有されない機能の一部:

  1. 生の SQL を使用する機能 - 標準の ANSI SQL で表現できないものを見つけるのは困難です。
  2. 継承マッピング - ここで個人的な意見を述べますが、ライブラリがこれを行うと、「邪魔にならないようにする」という原則に違反することがよくあると思います。

もちろん、Squeryl は、Python ライブラリにはない主要な機能と私が考える機能も提供します。これは、クエリの型安全性をコンパイラがチェックする機能です。

于 2012-05-10T16:57:44.520 に答える
7

ScalaQuery (一番下の「スリック」に関する注記を参照) は簡単に実行できます。

for{
  a <- Article
  if a.dateCreated between(start, end)
  _ <- Query groupBy a.reporterID orderBy a.dateCreated.desc
} yield(a)

または合成による任意の複合体:

val team = for{
  t <- Team
  s <- School if t.schoolID is s.id 
} yield (t,s)

val player = for{
  r <- Roster
  p <- Player if r.playerID is p.id
} yield (r, p)

val playerDetail = for{
  (r, p) <- player
} yield (p.id, p.firstName, p.lastName, r.jerseyID, r.position, r.gamesPlayed)

val scoring = for{
  (r, p) <- player
  s <- Scoring if p.id is s.playerID
  detail <- playerDetail 
} yield (r, p, s, detail)

val scoringDetail = for{
  (r, p, s, detail) <- scoring
  val (total, goals, assists) = 
    (s.playerID.count, s.goal.sum, (s.assist1.sum + s.assist2.sum))
  val ppg = (s.playerID.count / r.gamesPlayed)
} yield (goals, assists, total, ppg)

チームの統計情報を取得する方法は次のとおりです (リーグ ビューまたはシングル プレーヤー ビューでは変更される可能性があります)。

val forScoring = for{
  start ~ end ~ teamID <- Parameters[JodaTime,JodaTime,Int]
  (r,p,s,player) <- scoring if r.teamID is teamID
  comp <- bindDate(start, end) if s.gameID is comp.id
  (goals, assists, total, ppg) <- scoringDetail
  _ <- Query groupBy p.id orderBy ( ppg.desc, total.asc, goals.desc )
} yield (player, goals, assists, total, ppg)

def getScoring(start: JodaTime, end: JodaTime, id: Int): List[TeamScoring] = {
  forScoring(start, end, id).list
}

私は Scala で強く型付けされた複雑なクエリを生成できるとは思っていませんでした。つまり、私が ScalaQuery に出くわすまでは、これは Scala 言語自体によく似た啓示でした。

とにかく、オプションがあります。Squeryl は SQL Alchemy とより一致している可能性があります。わかりません。少し調べてみてください。失望することはないでしょう。提供されている Scala の利点は非常に多く、めまいを感じずにはいられませんここ、今、そしてその後 ;-)

ps Scala Days Skills Matters でのZeiger と Vogt による素晴らしい講演SLICK (ScalaQuery の次の進化)

于 2012-05-10T21:39:49.640 に答える
7

最近タイプセーフ スタックに追加されたSlickを使用することもできます。

于 2012-08-16T13:30:18.863 に答える