用Slick持久化ScalaFxBean

一直想给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解决方案。

你可能感兴趣的:(JavaFX,slick,ScalaFX)