zoukankan      html  css  js  c++  java
  • Grails的数据库相关开发



    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  
            } 
        } 


    以上两节留待以后验证
  • 相关阅读:
    超级详细Tcpdump 的用法
    Javascript网站繁简转换解决方案
    IIS6.0下创建用户隔离模式FTP站点
    如何开启IIS里的FTP主动模式(PASV模式)
    C#正则表达式小结
    ServU权限提升再提升记一次虚拟主机入侵
    Linux命令网络操作之ifconfig
    创建使用 Active Directory 模式隔离用户的新 FTP 站点
    远程控制电脑创建影子帐户(后门)
    Linux shell编程笔记总结
  • 原文地址:https://www.cnblogs.com/iamconan/p/7383448.html
Copyright © 2011-2022 走看看