一直想给ScalaFX找一个合适的持久曾框架,要越方便越好。
接触Scala之前玩的是JavaFX,曾用熟悉的Mybatis写持久层,JavaFxBean的Properties不能用IDE自动生成用于Mybatis的getter和setter。比方说一个属性
private fianl IntegerProperty age = new SimpleIntegerProperty(this, "age", 20);
用Eclipse或IDEA可以生成如下getter和setter
public IntegerProperty getAge() {
return age;
}
public void setAge(IntegerProperty age) {
this.age = age;
}
然而持久层框架需要的(也就是JavaFxBean的标配)是这样的getter和setter
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
自己写过一个简单的工具用来生产这样的getter和setter,但仍嫌麻烦。
(IDEA12.1已经支持生成JavaFX风格的getter和setter了)
(技术选型中,不喜请略过)
如今转向ScalaFX,Scala自带的BeanProperty注解生产的getter和setter也是JavaBean风格的,而IDEA12.1提供的便利也指望不上。所以一直在找替代方案。期间看到了OrientDB,这是一个纯Java的嵌入式NoSQL数据库,我是很看好它的,它甚至还提供了一个直接将JavaBean映射为Document的object模块。然而最大的问题是,object模块是直接映射Field,而不是getter和setter(源码中似乎是支持getter和setter的,因为是春节期间看的源码,再加上用的破笔记本,看不太仔细),同时对final字段会排出在外(而用val声明的字段恰好是final的)。本来想要改造orientdb-object模块,但并没有特别好的解决方案。
前些天学Play2的过程中Slick进入了我的视线,真正做到了零配置,也不需要写SQL。
(说实在的,为了做一个简单的查询,又要写建表语句,又要写各种SQL文,然后创建各种JavaBean,还有就是一堆配置文件,啊,简直要疯了。最好能省则省啊。)
本来JPA是个好选择,但是看网上JPA教材的时候第一眼看到了配置文件,我对配置文件那个烦啊(主要是记性不好,没IDE提示完全不知道怎么写),然后就不管它了。Slick好,没有配置文件,不需要写SQL(但需要定义Schema),那么就它吧。
(选型完毕,继续)
首先要声明一个ScalaFxBean,简单起见,只定义两个属性
class Person(_name: String, _age: Int) {
def this() = this(null, 0)
lazy val name = new StringProperty(this, "name", _name)
lazy val age = new IntegerProperty(this, "age", _age)
def name_=(v: String) {
name() = v
}
def age_=(v: Int) {
age() = v
}
override def toString = s"name = ${name()}; age = ${age()}"
}
这种类声明方式是参照ProJavaFX2中Scala and JavaFX一节。
Slick提供三种方式访问数据库(具体请在Slick官网了解),这里用的是叫做Lifted的方式,它实际上是将数据看作Tuple,我们需要将Tuple映射成对象(通过apply和unapply方法)
def apply(name: String, age: Int) = new Person(name, age)
def unapply(p: Person) = Option((p.name(), p.age()))
然后是定义Schema,我把apply和unapply也整合进来
object Persons extends Table[Person]("persons") {
def name = column[String]("name", O.NotNull)
def age = column[Int]("age")
def * = name ~ age <>(Persons.apply _, Persons.unapply _)
def apply(name: String, age: Int) = new Person(name, age)
def unapply(p: Person) = Option((p.name(), p.age()))
}
然后就可以操作数据了
object UsePerson extends App {
val p = new Person("misty", 23)
val db = Database.forURL("jdbc:h2:mem:test1", driver = "org.h2.Driver")
val ddl = Persons.ddl
db withSession {
ddl.create
Persons.insert(p)
val q = Query(Persons)
q foreach println
ddl.drop
}
}
也算是比较简洁了,但还有个缺点,就是ScalaBean和Schema之间有重复声明的感觉。
其实JPA可以算是将Schema以注解的方式合并到JavaBean中。明天再试试JPA(如果有精力的话),可惜没有Scala的JPA解决方案。
来源:oschina
链接:https://my.oschina.net/u/580483/blog/115300