web-dev-qa-db-ja.com

どのORMがScalaでうまく機能しますか?

MySQLデータベースに依存するScalaコマンドラインアプリケーションを作成しようとしています。ORMを探していましたが、うまく機能するものを見つけるのに苦労しています。

Lift ORM は見栄えが良いですが、LiftWebフレームワーク全体から切り離すことができるかどうかはわかりません。 ActiveObjectsも問題ないように見えますが、作者はScalaではうまく機能しない可能性があると述べています。

私はJavaからScalaに来ていないので、すべてのオプションがわかりません。ScalaでORMを使用した人はいますか?作業?

41

JPA指向のフレームワーク(Hibernateなど)が慣用的なScalaアプリケーションにエレガントに適合しない理由はいくつかあります:

  • 状態としてネストされた注釈はありません Scala 2.8 Preview -これは、複雑なアプリケーションのマッピングメタデータとして注釈を使用できないことを意味します(最も単純なものでも@JoinTable-> @JoinColumn);
  • ScalaとJavaコレクションは、開発者にコレクションを変換させます。また、Scalaコレクションをマッピングできない場合もあります。基盤となるフレームワークの複雑なインターフェース(HibernateのPersistentCollectionsなど)を実装せずにアソシエーションに。
  • ドメインモデルの検証など、いくつかの非常に一般的な機能では、永続クラスでJavaBeansの規則が必要です。これらは、物事を行うための「Scalaの方法」ではありません。
  • もちろん、相互運用の問題(Rawタイプやプロキシなど)は、簡単に歩き回ることができないまったく新しいレベルの問題をもたらします。

他にも理由があると思います。そのため、 Circumflex ORMプロジェクト を開始しました。この純粋なScalaORMは、古典的なJava ORMの悪夢を排除するのが最善です。具体的には、古典的なDDLステートメントでこれを行うのとほぼ同じ方法でエンティティを定義します。

class User extends Record[User] {
  val name = "name".TEXT.NOT_NULL
  val admin = "admin".BOOLEAN.NOT_NULL.DEFAULT('false')
}

object User extends Table[User] {
  def byName(n: String): Seq[User] = criteria.add(this.name LIKE n).list
}

// example with foreign keys:
class Account extends Record[Account] {
  val accountNumber = "acc_number".BIGINT.NOT_NULL
  val user = "user_id".REFERENCES(User).ON_DELETE(CASCADE)
  val amount = "amount".NUMERIC(10,2).NOT_NULL
}

object Account extends Table[Account]

ご覧のとおり、これらの宣言は、従来のJPAPOJOよりも少し冗長です。しかし実際には、一緒に組み立てられるいくつかの概念があります。

  • スキーマを生成するための正確なDDL(同じDSLのような方法でインデックス、外部キー、その他のものを簡単に追加できます)。
  • すべてのクエリは、DAO内に散らばる代わりに、その「テーブルオブジェクト」内で組み立てることができます。クエリ自体は非常に柔軟性があり、クエリオブジェクト、述語、射影、サブクエリ、リレーションエイリアスを変数に格納して、再利用したり、作成したりすることができます。既存のクエリからのバッチ更新操作(たとえば、挿入-選択)。
  • アソシエーション間の透過的なナビゲーション(1対1、多対1、1対多、および多対多から中間の関係)は、怠惰な戦略または熱心なフェッチ戦略のいずれかによって実現できます。どちらの場合も、関連付けは、基礎となる関係の外部キーの上に確立されます。
  • 検証はフレームワークの一部です。
  • スキーマを生成し、便利なXML形式のファイルから初期データをインポートできるMaven2プラグインもあります。

CircumflexORMに欠けているのは次のとおりです。

  • 複数列の主キー(複数列の一意の制約に裏打ちされた複数列の外部キーを作成することは可能ですが、データの整合性のためだけです)。
  • 本格的なドキュメント(私たちは積極的に取り組んでいますが)。
  • circumflexORMをコアテクノロジーとする100億ドル規模の生産システムのサクセスストーリー。

P.S.この投稿が広告と見なされないことを願っています。そうではありません。私はできるだけ客観的になるように努めていました。

34
incarnate

EclipseLink JPA で実験しましたが、基本的な操作は問題なく機能しました。 JPAはJava標準であり、他にも機能する可能性のある実装があります( OpenJPA など)。 ScalaのJPAクラスがどのように見えるかの例を次に示します。

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity { val name = "Users" }
class User {
  @Id
  @GeneratedValue
  var userid:Long = _

  var login:String = _

  var password:String = _

  var firstName:String = _

  var lastName:String = _
}
9
dkaylor

Scala用の新しいORMライブラリの最初のリリースを発表できることをうれしく思います。 MapperDaoは、ドメインクラスをデータベーステーブルにマップします。現在、mysql、postgresql(Oracleドライバーは間もなく利用可能)、1対1、多対1、1対多、多対多の関係、自動生成されたキー、トランザクションをサポートし、オプションでSpringとうまく統合します。フレームワーク。これにより、永続性の詳細に影響されないドメインクラスの設計に自由が与えられ、不変性が促進され、タイプセーフになります。ライブラリはリフレクションに基づいているのではなく、優れたScala設計原則に基づいており、selectクエリによく似たデータをクエリするDSLが含まれています。equals()やhashCode()の実装は必要ありません。 )永続化されたエンティティにとって問題となる可能性のあるメソッド。マッピングは、タイプセーフScalaコードを使用して行われます。

詳細と使用方法については、mapperdaoのサイトをご覧ください。

http://code.google.com/p/mapperdao/

ライブラリは、上記のサイトからダウンロードでき、Mavenの依存関係としても入手できます(ドキュメントには、Mavenを介してライブラリを使用する方法の詳細が含まれています)

例は次の場所にあります。

https://code.google.com/p/mapperdao-examples/

コードサンプルによるライブラリの非常に簡単な紹介:

class Product(val name: String, val attributes: Set[Attribute])
class Attribute(val name: String, val value: String)
...

val product = new Product("blue jean", Set(new Attribute("colour", "blue"), new Attribute("size", "medium")))
val inserted = mapperDao.insert(ProductEntity, product)
// the persisted entity has an id property:
println("%d : %s".format(inserted.id,inserted))

クエリは非常によく知られています。

val o=OrderEntity

import Query._
val orders = query(select from o where o.totalAmount >= 20.0 and o.totalAmount <= 30.0)
println(orders) // a list of orders

ライブラリを使用してフィードバックを提供することをお勧めします。ドキュメントは現在非常に広範囲で、セットアップと使用方法の説明があります。 googlemail dotcomのkostasdot kougiosにコメントして、私に連絡してください。

ありがとう、

コスタンティノスコウギオス

これは基本的に@Columnアノテーションを使用した同じ例です。

 /*
   Corresponding table:

 CREATE TABLE `users` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) default NULL,
  `admin` tinyint(1) default '0',
  PRIMARY KEY  (`id`)
) 

*/

import _root_.javax.persistence._

@Entity
@Table{val name="users"}
class User {

  @Id
  @Column{val name="id"}
  var id: Long = _

  @Column{val name="name"}
  var name: String = _

  @Column{val name="admin"}
  var isAdmin: Boolean = _

  override def toString = "UserId: " + id + " isAdmin: " + isAdmin + " Name: " + name

}
2
Ikai Lan

Slick は機能的な世界にぴったりです。従来のORMはScalaに完全には適合しません。 Slickはうまく構成され、Scalaコレクションクラスを模倣し、理解するためにDSLを使用します。

2
Jack

もちろん、任意のJavaデータベースアクセスフレームワークはScalaでも機能し、コレクションの変換など、通常発生する可能性のある問題があります。jOOQたとえば、Scalaでうまく機能することが観察されています。ScalaのjOOQコードの例は、マニュアルに記載されています。

object Test {
  def main(args: Array[String]): Unit = {
    val c = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
    val f = new Factory(c, SQLDialect.H2);
    val x = T_AUTHOR as "x"

    for (r <- f
        select (
          T_BOOK.ID * T_BOOK.AUTHOR_ID,
          T_BOOK.ID + T_BOOK.AUTHOR_ID * 3 + 4,
          T_BOOK.TITLE || " abc" || " xy"   
        )
        from T_BOOK
        leftOuterJoin (
          f select (x.ID, x.YEAR_OF_BIRTH)
          from x
          limit 1
          asTable x.getName()
        )
        on T_BOOK.AUTHOR_ID === x.ID
        where (T_BOOK.ID <> 2)
        or (T_BOOK.TITLE in ("O Alquimista", "Brida"))
        fetch
    ) {
      println(r)
    }
  }
}

http://www.jooq.org/doc/2.6/manual/getting-started/jooq-and-scala/ から取得

1
Lukas Eder