首页 > 代码库 > Grails框架之Domain与GORM

Grails框架之Domain与GORM

一 Grails概述

     “Simplicity is the ultimate sophistication”-Lenardo da Vinci

如上艺术大师达芬奇所述,“简约是最终的复杂形式”,最美的东西往往是最本质、最简单的东西。Grails就是为了简化Java-Web企业级应用开发而生的轻量级开源框架。传统的Java程序员经历过编写复杂而令人生畏的XML配置文件,Grails基于“Convention is over Configuration”(约定大于配置)和“Don‘t Repeat Yourself”(不要重复造轮子)的开发理念,开发人员无需再手动编写复杂繁琐的配置,而将更多的精力专注于业务逻辑从而大大提高开发效率。Grails是构建于Spring和Hibernate之上的更高抽象层技术,其基于JVM并使用Groovy动态语言,可以无缝整合Java平台的开发技术。通俗来说,Grails即为基于传统Java开发技术之上而简化的专门用于快速构建小型Web应用的框架,其主要基于Hibernate、Spring、SiteMesh(一个健壮且稳定的页面布局渲染框架)、Tomcat、H2(一个利用纯Java技术实现的关系型数据库管理系统)。技术栈组件间关系如下图所示:

技术分享

确切说Grails是一个全栈的开发环境而不仅仅是个Web开源框架,由上图可以看出Grails完全基于Java生态系统,其中Groovy是由Java5衍生出来的更为灵活的动态语言,它和Java无缝融合,并基于JDK之上,共用绝大部分的API。因此,Java程序员掌握Grails框架是件容易的事情。

    Grails的优势主要体现在开发效率高,适用于快速构建小型的Web应用,可以满足大多数对系统要求不是很高的开发,但凡物必有其短。Grails是基于传统开源框架之上更高的抽象层技术,底层实现均已得到良好的封装,因此尚不能很好的胜任构建大型的企业级应用开发,这或许是Grails一直处于开源社区但却没有很好的推广的原因,所以给人的感觉此项技术很小众,缺乏良好的应用前景。架构上,Grails摈弃了传统的DAO层,直接分为view(视图)层、Controller(控制)层、Service(业务逻辑)层3 层架构,其具体请求处理逻辑如下图所示:

技术分享

二 Domain数据模型设计

    Domain实体类在任何的应用场景中都处于核心位置,它是数据的封装抽象形式,所以其重要性不言而喻。Grails框架中Domain实体类主要用于数据模型设计,可以定义其约束及实体类间关系,并映射为数据库的表间关系。案例是描述事物的良好方式,可以使得抽象复杂的概念具象化、简单化。假设现需构建一个在线歌曲商城应用,用户可以购买歌曲,评论歌曲,预览歌曲等,为简化描述问题先不考虑系统的实现方式,按需求分析该应用至少比包括Artist(艺术家)、Album(专辑)、Song(歌曲)3个实体,每个实体具有其特有的属性,约定每位Artist(艺术家)将拥有多张Album(专辑),而每张专辑收录多首Song(歌曲)。

   数据持久化是开发中经常应用的操作,Grails将每一个实体类映射为数据库中的一张表,属性映射为对应字段。为保证数据的完整性和避免产生脏数据,Grails Domain Class可以同时设置约束和表间关系。Grails为domain class之间提供了多种关系,包括one-to-one(最简单),比如Car和Engine之间是一对一的关系

 

Class Car{    Engine engine}Class Engine{   Car car}

 

该模型间是双向的一对一关系,并没有从属关系,但在实际情况中,我们会经常遇到实体间的从属关系,例如An Engine belongs to a Car,but a Car does not belong to an Engine  Grails提供实现该关系的机制。

Class car{    Engine engine}Class Engine{    static  belongsTo=[car:Car]}//An Engine belongs to a Car

Engine类中belongsTo属性值是一个Map,键值key是car(Car类的引用),belongsTo表明Car实体是关系的拥有者,此时数据库中Car表中引用Engine主键id作为其外键,但Engine表中并无外键应用。若想Engine中引用Car表的主键id作为其外键,可以将二者的关系定义为:

Class Car{    Engine engine   static hasOne=[engine:Engine]}Class Engine{    static belongsTo=[car:Car]}

若An Engine belongsTo a Car,but has no reference to its owner,可以定位Engine实体为:

Class Engine{   static belongsTo=Car}//此时Engine表中并无引用Car表的外键

回归到案例本身,Grails中one-to-many同样非常简单,按需求分析得:(Artist与Album之间为1对多关系;Album与Song之间也为一对多关系),在定义关系的同时同时可以定义约束:

//艺术家class Artist {    String name    static constraints = {       name(nullable: false,unique: true)//定义非空唯一约束    }    static mapping = {        version(false) //消除version默认属性        id:‘identity‘ //主键自增    }    static hasMany = [albums:Album] //与Album建立一对多关系}//专辑class Album {    String title    static constraints = {    }    static mapping = {        version(false)        id:‘identity‘    }    static hasMany = [songs:Song] //与Song建立一对多关系    static  belongsTo = [artist:Artist]  //Album表外键引用Artist表的主键}//歌曲class Song {    String title    Integer duration //歌曲时长    static constraints = {        title (blank: false,unique: true)    }    static mapping = {        version(false)        id:‘identity‘        duration(min:1)    }    static  belongsTo = [album:Album] //Song表中外键应用Album表主键}

此时实体间关系为: 此时数据库中映射为Artist、Album、Song三张表,其中Artist与Album以artist_id关联,Album与Song以Album_id关联。

技术分享

Hibnerate对Grails底层做了良好的封装,使得常规的CRUD操作变得异常简单,实体类只需调用API即可完成数据持久化操作,在此不再展开描述

二 GORM原理

 

Grails框架之Domain与GORM