我即将编写一个依赖于MySQL数据库的Scala命令行应用程序。我一直在寻找ORM,并且找不到合适的ORM。
Lift ORM看起来不错,但我不确定它是否可以与整个Lift Web框架分离。 ActiveObjects看起来还不错,但是作者说它可能不适用于Scala。
我不是来自Java的Scala,所以我不知道所有选项。有没有人使用过Scala的ORM,如果有的话,你使用了什么以及它的效果如何?
答案 0 :(得分:34)
有几个原因可以解释为什么面向JPA的框架(例如Hibernate)不能很好地适应惯用的Scala应用程序:
@JoinTable
- > @JoinColumn
); PersistentCollections
),就无法将Scala集合映射到关联; 我确信还有更多原因。这就是我们开始Circumflex ORM project的原因。这个纯Scala ORM试图消除经典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]
正如您所看到的,这些声明比经典的JPA POJO更冗长。但实际上有几个概念组合在一起:
Circumflex ORM缺乏的唯一内容是:
P.S。我希望这篇文章不会被视为广告。实际上并非如此 - 我试图尽可能客观。
答案 1 :(得分:9)
我尝试了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 = _
}
答案 2 :(得分:4)
我很高兴宣布为Scala推出新的ORM库。 MapperDao将域类映射到数据库表。它目前支持mysql,postgresql(即将推出的oracle驱动程序),一对一,多对一,一对多,多对多关系,自动生成的密钥,事务,并可选择与spring完美集成框架。它允许自由设计不受持久性细节影响的域类,鼓励不变性并且类型安全。该库不是基于反射,而是基于良好的Scala设计原则,并包含用于查询数据的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 dot com的kostas dot kougios与我联系。
谢谢,
Kostantinos Kougios
答案 3 :(得分:2)
这里的@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
}
答案 4 :(得分:2)
Slick是功能性世界的完美搭档。传统的ORM不适合Scala。光滑的构图很好,并使用模仿Scala集合类和理解的DSL。
答案 5 :(得分:1)
当然,任何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/