Grails的数据库相关开发

mac2022-06-30  98

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           }      }  }  以上两节留待以后验证

转载于:https://www.cnblogs.com/iamconan/p/7383448.html

相关资源:grails开发环境配置及应用开发
最新回复(0)