1.开发domain和service







在出来的输入框里输入domain的名字,可以包括包名。

这里我输入test.domain.House,点finish



创建了两个groovy文件,一个当然是test.domain.House.groovy,另一个是test.domain.HouseTests.groovy.

先说test.domain.House.groovy。这个就是传说中的POGO。Grails会在运行时给他注入很多方法。



现在给他增加两个属性:



Groovy代码  收藏代码

package test.domain 

 

class House { 

     

    String name 

    String address 

 

    static constraints = { 

 

    } 







新建一个service(方法参见上一篇),名称可以直接输入House的类全名。

编辑生成的service单元测试:



Groovy代码  收藏代码

package test.domain 

 

 

 

import grails.test.mixin.* 

import org.junit.* 

 

/** 

* See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions 

*/ 

@TestFor(HouseService) 

@Mock(House) 

class HouseServiceTests { 

 

    void testFindByAddress() { 

        new House(name:"Beautiful House",address:"No.1").save(); 

        def house = service.findByAddress("No.1") 

        assert house != null 

        println house.id 

    } 





注意这一行:

println house.id



之前并没有给House定义ID,GORM会默认给他加上一个ID。

另外说一下@Mock(House)。因为domain要在grails运行时才会给domain注入方法,如果在单元测试的时候可以使用Mock这个annotation,给House这个domain注入运行时的模拟方法。



实现一下service:



Groovy代码  收藏代码

package test.domain 

 

class HouseService { 

 

    def findByAddress(String address) { 

        return House.findByAddress(address) 

    } 





findByAddress就是一个动态生成的方法,可以让我们按地址查找。



运行一下HouseServiceTests这个单元测试:







当然也可以先debug,跑完以后会弹出打开 TESTS-TestSuites.xml  这个文件。点下面的sheet切换:





就可以看到test里打的println了:



<system-out><![CDATA[--Output from testFindByAddress--

1

]]></system-out>





这个XML的格式不解释。



service需要加事务吧:



Groovy代码  收藏代码

package test.domain 

 

import org.springframework.transaction.annotation.Transactional; 

 

class HouseService { 

 

    @Transactional(readOnly=true) 

    def findByAddress(String address) { 

        return House.findByAddress(address) 

    } 



依然可以使用spring的@Transactional。当然也有别的方法。暂时不写了。

2.domain的验证



test.domain.HouseTests.groovy 不明白为什么要生成这个测试单元。方法都是Grails注入的,MS没什么好测的。

现在拿来做测试验证吧。

给test.domain.House.groovy加多几个属性:



Groovy代码  收藏代码

package test.domain 

 

class House { 

     

    String name 

    String type 

    String desc 

    String address 

    Date buildedDate 

    Float price; 

 

    static constraints = { 

        type inList:["common","bungalow","villa"],nullable:true 

        desc maxSize:1000,nullable:true 

        buildedDate max:new Date(),nullable:true 

        price max:98765432109876543210f,scale:2,nullable:true 

    } 







重点看下边的constraints。这里定义属性的约束 ,选了几个典型的。

inList,适用于枚举。

desc这种属于大文本,字符串默认在数据库里会变成 varchar(255) ,定义了最大值就会成为TEXT

bulidedDate这种属于历史时间,不应当晚于当前时间。参照这种定义方法。

price属于浮点,定义最大最小值的时候需要注意要是浮点数(注意最后的f),默认的scale是3





测试代码如下:



Groovy代码  收藏代码

package test.domain 

 

 

 

import grails.test.mixin.* 

import grails.test.mixin.domain.DomainClassUnitTestMixin; 

 

import org.junit.* 

 

/** 

* See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions 

*/ 

@TestFor(House) 

class HouseTests { 

 

    void testSomething() { 

        mockForConstraintsTests(House) 

        def house = new House(name:"House1",type:"unknown"); 

         

        assert !house.validate() 

        println house.errors["type"] 

    } 







mockForConstraintsTests(House)是内置的给domain加上验证框架的内置方法的一个mock。house.validate()用于验证所有定义的约束,可以用在web和service里,house.errors["属性名"]可以查违反的约束。



运行测试可以看到结果。



3.domain间的关系





关于一对一,多对对,一对多,多对一的这些个关系,官方的reference写得挺清楚,不翻译了。

不过得注意一下这个belongsTo

如让房子有个主人:



Groovy代码  收藏代码

package test.domain 

 

class House { 

     

    String name 

    String type 

    String desc 

    String address 

    Date buildedDate 

    Float price; 

     

    static belongsTo = [owner:Person] 

 

    static constraints = { 

        type inList:["common","bungalow","villa"],nullable:true 

        desc maxSize:1000,nullable:true 

        buildedDate max:new Date(),nullable:true 

        price max:98765432109876543210f,scale:2,nullable:true 

    } 



package test.domain

Groovy代码  收藏代码

class Person { 

     

    String name 

    static hasMany = [houses:House] 

 

    static constraints = { 

    } 





这时房子从属于人,当人删除的时候会对房子造成级联删除。有一定危险,使用的时候要注意。



由于不知道怎么在单元测试里检验下面要说的东西所以……

以下内容属于道听未经验证



4.多数据源



假设第二个数据源叫datasoruce_second,配置如下



Groovy代码  收藏代码

environments { 

    development { 

        dataSource { 

            dbCreate = "create-drop" 

            url = "jdbc:h2:mem:devDb" 

        } 

        dataSource_second { 

            dialect = org.hibernate.dialect.MySQLInnoDBDialect 

            driverClassName = 'com.mysql.jdbc.Driver' 

            username = 'root' 

            password = 'root' 

            url = 'jdbc:mysql://localhost/root' 

            dbCreate = 'update' 

        } 

    } 

    test { 

        dataSource { 

            dbCreate = "update" 

            url = "jdbc:h2:mem:testDb" 

        } 

    } 

    production { 

        dataSource { 

            dbCreate = "update" 

            url = "jdbc:h2:prodDb" 

        } 

        dataSource_second { 

            dialect = org.hibernate.dialect.Oracle10gDialect 

            driverClassName = 'oracle.jdbc.driver.OracleDriver' 

            username = 'root' 

            password = 'root' 

            url = 'jdbc:oracle:thin:@localhost:1521:root' 

            dbCreate = 'update' 

        } 

    } 





如果人这个表用的这个数据源:

Groovy代码  收藏代码

package test.domain 

 

class Person { 

     

    String name 

    static hasMany = [houses:House] 

 

    static constraints = { 

        datasources(["second"])  

    } 





另外还可以引入别的datasource的包,把数据源当成spring的bean注入到程序里使用。

5.直接执行SQL



一种方法当然是写java代码,然后groovy当bean来调用,这种感觉用groovy用得比较假。。。

直接写SQL的形如:



Groovy代码  收藏代码

package test.sql 

 

import groovy.sql.Sql 

 

class SQLTestService { 

     

    def dataSource 

 

    def sqlRun() { 

        def db = new Sql(dataSource) 

        db.eachRow('select * from house'){  

            println it  

        } 

    } 





以上两节留待以后验证

Grails的数据库相关开发的更多相关文章

  1. MySQL数据库相关开发入门

    使用apt-get来进行MYSQL数据库的安装,安装好以后就可以使用数据库了. 命令行键入mysql即可进入(因为数据库初始化的没有密码的):当然为了安全,你最好还是创建一个用户和密码. 当你创建过用 ...

  2. Atitit  基于meta的orm,提升加速数据库相关应用的开发

    Atitit  基于meta的orm,提升加速数据库相关应用的开发 1.1. Overview概论1 1.2. Function & Feature功能特性1 1.2.1. meta api2 ...

  3. 安卓项目-利用Sqlite数据库,开发新闻发布系统

    本教程致力于程序员可以快速的学习安卓移动端手机开发. 适合于已经习得一种编程语言的同仁. 更多志同道合,想要学习更多编程技术的大神们. 小弟不才,麻烦关注一下我的今日头条号-做全栈攻城狮. 本文章是基 ...

  4. PB数据库相关

    ---------------------------------------------------------------- 数据库画板: 一张表定义了主键或者唯一索引,则能够在Results视窗 ...

  5. Oracle数据库之开发PL/SQL子程序和包

    Oracle数据库之开发PL/SQL子程序和包   PL/SQL块分为匿名块与命名块,命名块又包含子程序.包和触发器. 过程和函数统称为PL/SQL子程序,我们可以将商业逻辑.企业规则写成过程或函数保 ...

  6. sourceforge.net安装网站程序数据库相关

    sourceforge.net安装网站程序数据库相关 我们应该知道sourceforge.net是可以安装网站(当做一个虚拟空间使用的) 但是在安装cms程序的时候那时的数据库地址再填写“localh ...

  7. python面试题包含基础和Linux操作以及数据库相关

    今天面试了一家公司,感觉表现的不是很好,记录一下面试的试题. python基础部分 python 是一门什么样的语言面向对象的语言有那些,python的面向对象和Java面向对象的区别 Python是 ...

  8. Oracle 数据库应用开发 30 忌

    原创 LaoYuanPython CSDN 今天 作者 | LaoYuanPython       责编 | 欧阳姝黎出品 | CSDN原力计划 引言 笔者及所在团队从 2000 年开始的 CRM 等 ...

  9. Android数据库相关整理

    今天对Android中数据库相关的操作和代码做了一个整理,便于自己之后的查阅.主要内容有: 1.原生数据库写法 2.终端进sqlite的操作 3.第三方库 4.事务处理 5.权限和路径 一.原生数据库 ...

  10. php与数据库代码开发规范

    php与数据库代码开发规范 1/25/2016 6:00:31 PM php对各类变量命名规范 目录名 文件命名 局部变量命名 使用英文动词名词,用下划线作为单词的分割,所有字母均使用小写 目录 up ...

随机推荐

  1. 主机--Host

    概念:主机是用于构建应用程序和服务.封装应用资源的对象,负责程序的启动和生命周期的管理,简单来说主机即应用程序. 主机运行:当主机运行的时候,他会将托管在服务容器集合里面注册的IHostService ...

  2. 单片机 IAP 功能进阶开发篇之BOOT升级(一)

    引言 目的 主要介绍单片机 IAP 开发的设计思路,如何不使用下载烧录器的方式对单片机的程序进行升级,升级区域包括 bootloader 和用户程序的升级,升级方式有 UASRT 通信.CAN 通信和 ...

  3. [Elasticsearc] Elasticsearch 初见

    Elasticsearch 初见 启动 双击 bin 目录下的 elasticsearch.bat 文件,等待终端运行成功 索引的增删改查 增(PUT) postman 发送请求 PUT 请求:htt ...

  4. ArrayList中的遍历删除

    ArrayList 中的遍历删除 在代码编写过程中经常会遇到这样的要求:遍历一个线性表,要求只遍历一遍(时间复杂度\(O(n)\)),删除符合指定条件的元素,且要求空间复杂度 \(O(1)\). 例如 ...

  5. 源码剖析Spring依赖注入:今天你还不会,你就输了

    在之前的讲解中,我乐意将源码拿出来并粘贴在文章中,让大家看一下.然而,我最近意识到这样做不仅会占用很多篇幅,而且实际作用很小,因为大部分人不会花太多时间去阅读源码. 因此,从今天开始,我将采取以下几个 ...

  6. NC20960 迪拜的超市

    题目链接 题目 题目描述 forever97家住迪拜一环,因此有很多大大小小的商场. 迪拜一环有n个超市,分别在坐标轴[1,n]位置,forever97家在0这个位置. 由于日常开销巨大,所以Trot ...

  7. springboot中前端ajax如何给controller提交数组参数?

    说明 我有个需求,前端批量添加一堆商品明细.也就是说会有一个商品ID,然后一堆商品明细,多行. 如此一来,针对后端接口肯定是要以数组或列表方式接收这个商品明细数组了. 前端代码 关键地方在于以form ...

  8. 【Android 逆向】【攻防世界】黑客精神

    1. apk 安装到手机,提示输入注册码 2. jadx打开apk MainActivity.java @Override // android.app.Activity public void on ...

  9. Qt开发技术:QCharts(二)QCharts折线图介绍、Demo以及代码详解

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  10. 【ACM专项练习#01】基本输入输出,如何加减

    关于ACM,牛客其实也有专门的模拟练习:https://ac.nowcoder.com/acm/contest/5657#question 做这个也可以 关于while(cin>>n) 在 ...