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


    以上两节留待以后验证
  • 相关阅读:
    HDU 3401 Trade
    POJ 1151 Atlantis
    HDU 3415 Max Sum of MaxKsubsequence
    HDU 4234 Moving Points
    HDU 4258 Covered Walkway
    HDU 4391 Paint The Wall
    HDU 1199 Color the Ball
    HDU 4374 One hundred layer
    HDU 3507 Print Article
    GCC特性之__init修饰解析 kasalyn的专栏 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/iamconan/p/7383448.html
Copyright © 2011-2022 走看看