如今,ORM几乎是所有企业开发项目的标配,在Grails中,它的ORM解决方案是GORM。
GORM的基础是Hibernate3,虽然GORM已经极大简化了Hibernate的使用,但是要想真正用好GORM,对于Hibernate的理解是必须的。
为了对GORM有个感性认识,我们先来看看如何在Grails中实现对数据的CRUD操作。首先,我们可以简单地认为,凡是要保存到数据库中对象都要实现为Grails的Domain Class。Domain Class的创建过程如下:
1. 使用grails create-domain-class命令,如:
grails create-domain-class person
2. 创建完成的Domain Class保存在grails-app/domain目录下。
3. 接下来就是编辑产生的Domain Class,使之符合我们的要求:
class Person { String name Integer age Date lastVisit }
现在,Domain Class已经创建完毕,该是考虑如何把Domain Class保存到数据库的时候了。典型的数据库操作是C(增)、R(读)、U(改)、D(删)。如果你是第一次接触Grails,相信你会有一种在黑暗的Java开发中看到光明的感觉:
1. 创建(C)
def p = new Person(name:"Fred", age:40, lastVisit:new Date()) p.save()
2. 读取(R)
//for修改 def p = Person.get(1) //for只读,此时Hibernate将不会进行“脏检查” def p= Person.read(1)
3. 更新(U)
def p = Person.get(1) p.name = "Bob" p.save()
4. 删除(D)
def p = Person.get(1) p.delete()
借助Groovy语言的动态特性,在Grails中完全消除了写DAO的必要性。要是你还有什么疑惑的话,那肯定是会“我没有定义那些方法呀,怎么自己就突然冒出来了?”,别着急,跟着这个系列,你就会慢慢清楚的;)。现在,你只需要记住,凡是Grails中的Domain Class,都可以直接调用那几个方法。
看完CRUD操作,就应该实际了解一下在Grails中创建Domain Class的相关知识的事情了。因为在现实项目中,Domain Class通常不会一个个独立存在,与其他Domain Class不发生任何关系;此外,对于Hibernate熟悉的读者也会知道Hibernate是支持组件、继承、集合的,这些在Grails中又是如何实现的呢?
首先,让我们来回顾一下我们对于Hibernate的一些建模方面的基础知识:
使用过Hibernate的开发人员对于既要写Java类又要编辑映射文件应该不会太陌生,虽然后面Hibernate也推出了映射的Annotation,但是依然显得繁琐。在Grails中,这些统统都得到了简化,很多时候,你只需要在Domain Class中去书写Groovy代码就可以了。
对于类之间的关联定义,Grails中主要有这么几种:
考虑到关系的方向性以及级联,对于one-to-one的映射大概有:
one-to-one还有一种定义关联的属性:hasOne,使用它时,必须是双向的:
//5 class Face { static hasOne= [nose: Nose] } class Nose { Face face }
one-to-one对产生的关系表的影响:
在Grails中,不必明显的定义出many-to-one,因为引用一个对象就有这一层意思在里面了。而定义one-to-many,则是使用hasMany来完成的,但与hasOne不一样,它的使用不必是双向的。即你可以只使用hasMany,而另一端无需定义任何关联属性。one-to-many同样有以上那几种情况,使用完全类似,因此这里就不一一列出,在此只列出双向/级联的情况:
class Author { static hasMany = [ books : Book ] String name } class Book { static belongsTo = [author:Author] String title }
说belongsTo定义了级联并不完全正确,它实际定义的是级联删除。如果不定义,缺省级联特性为插入和更新。
one-to-many对产生关系表的影响,其中(A和B是一对多关系):
对于以上第一种情况,表示的是A和B之间可选的一对多关系,即B有可能没有A。对于这种情况,就需要引入关联表。关于这部分的讨论,请参见《Java Persistence with Hibernate》。
最后一种关系类型就是many-to-many了,它必然是双向的,而且一方必须指定belognsTo:
class Book { static belongsTo = Author static hasMany = [authors:Author] String title } class Author { static hasMany = [books:Book] String name }
many-to-many最终产生的是关联表,此外,这里需要纠正一下文档的错误:
Grails从1.1起就已经支持many-to-many的scaffolding了。
以上的关联定义都只是一个关系定义对应一个关联属性,但在项目中可能还会出现其他情况:
|