GORM Mapping Manifesto ::要么长也要不长

vir*_*yes 4 testing grails hibernate grails-orm

相当基本的问题,但它的根源深入到框架中(并且关于这个主题几乎没有确切的信息),所以我把它放在这里以便拯救他人的痛苦(并且在我的思考中验证我是否正确) ).

问题是什么?

Grails会自动将一个类型为Long的id字段注入您的域(请参阅Beckwith的评论).使用遗留数据库Grails时默认情况下将Longs映射为bigint,这是一种低效的存储类型,任何处理大量+记录表的人都会避免这种情况.

几个月前发现这一点后,我开始着手为我的域ID获取"适当的"列类型.没有Java背景,盲目地我想,Long-bad,Integer-good并将整数类型的hibernate映射方言设置为我将在mysql中手动执行的操作

registerColumnType(Types.INTEGER,'mediumint unsigned')

然后在我的所有域中定义"整数id"(根据Bert在上面链接中的评论,没有必要).一切都在游泳,美妙,在其他事情上发挥作用.

快进到Grails 2.0(因为我无法抗拒所有的好东西;-))和Spock.对于我的生活,我无法弄清楚为什么,尽管2.0新的内存GORM和对动态查找器的支持,Domain.findByFoo(fooVal)总是会返回null(是的,我@Mock(域)并填充测试数据).实际上,在测试本身和@TestFor目标中,唯一有效的GORM方法是save()和get(); 其他一切都返回null.

我掀起了一个快速测试应用程序,域名+控制器+ spoc规范并发现了问题的根源:如果你使用除Long以外的属性类型(包括引用的FK),你的@Mock域名将被渲染无用.

那么,我是否正确地说必须使用Long ID才能充分利用框架?@Mock + @TestFor + Spock是一个令人难以置信的组合!在我走向重构到长路之前,指导得到了赞赏......

Dón*_*nal 5

我无法想象任何真实的场景,其中Integer和Long之间的差异会对性能产生任何显着的差异(这似乎是进行此更改的最初动机).

如果使用Long工作,但Integer会导致问题,那么使用Long并转移到更重要的任务上.如果你能证明使用Integer产生任何显着的差异,我只会担心这一点.

更新

你是对的,我完全忽略了Grails自动用于Long的数据库类型.您似乎已经知道,您可以在域类的映射闭包中控制数据库类型,例如

class Person {
   Long id

   static mapping = {
      // See here for alternatives to integer, and how they map to DB types
      // http://docs.jboss.org/hibernate/stable/core/manual/en-US/html/mapping.html#mapping-types-basictypes
      id type:'integer'
   }
}
Run Code Online (Sandbox Code Playgroud)

你还提到了评论

在代码级别处理Long,其中必须指定def foo(Long id){...}和params.id.toLong()而不是Integer

您可以简单地将操作定义为

def myAction = {Person p ->

}
Run Code Online (Sandbox Code Playgroud)

要么

def myAction = {
   Person p = new Person(params)
}
Run Code Online (Sandbox Code Playgroud)

Grails将负责将id请求参数转换为类型Person.id,无论它是Long,Integer,BigDecimal等.