【问题标题】:GORM Mapping Manifesto :: To Long or not to LongGORM 映射宣言 :: To Long or not to Long
【发布时间】:2011-11-27 18:01:30
【问题描述】:

相当基本的问题,但它的根源深深植根于框架中(关于该主题的确切信息很少),所以我把它放在这里是为了减轻其他人的痛苦(并验证我是否正确在我看来)。

有什么问题?

Grails 自动将 Long 类型的 id 字段注入您的域 (see Beckwith's comment)。当使用传统的 DB Grails 时,默认情况下会将 Longs 映射到 bigints,这是一种低效的存储类型,任何处理百万以上记录表的人都会避免这种存储类型。

几个月前发现这一点后,我开始着手为我的域 ID 设置一个“正确”的列类型。没有Java背景,我盲目地认为,Long-bad,Integer-good并将整数类型的休眠映射方言设置为我在mysql中手动执行的操作

registerColumnType(Types.INTEGER, 'mediumint unsigned')

然后在我的所有域中定义“整数 id”(根据上面链接中 Bert 的评论不是必需的)。一切都很顺利,很棒,在其他事情上。

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

我创建了一个快速测试应用程序,域 + 控制器 + spoc 规范并发现了问题的根源:如果您的 id(包括引用的 FK)使用 Long 以外的属性类型,您的 @Mock 域将变得无用。

那么,我是否正确地说必须使用 Long id 才能充分利用该框架? @Mock + @TestFor + Spock 是一个令人难以置信的组合!在我走上重构之路之前,感谢您的指导......

【问题讨论】:

    标签: hibernate testing grails grails-orm


    【解决方案1】:

    我无法想象任何现实情况,其中 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'
       }
    }
    

    你也是在 cmets 长大的

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

    你可以简单地定义一个动作

    def myAction = {Person p ->
    
    }
    

    def myAction = {
       Person p = new Person(params)
    }
    

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

    【讨论】:

    • 谢谢,您认为您错过了重点:主要问题是关于 Grails 如何在遗留数据库中将 Long 映射到 bigint,这是一种效率极低的 PK 存储类型,在处理大桌子。在代码级别,我根本不关心 Long 与 Integer 的性能,但我想避免在 Groovy 默认为 Integer 用于数字类型时必须执行 params.id.toLong() 或其他转换箍跳跃之类的事情。如果错误,请纠正,也许这完全没有根据,grails 会自动为我们转换数字类型,但我有疑问......
    • 再想一想,在数据库级别将 Long 映射到 mediumint 而不是 bigint 很容易解决,所以剩下的未知问题是:在代码级别处理 Long 必须指定 def foo(Long id) {...} 和 params.id.toLong() 而不是整数,我假设每个人的代码都是默认的。例如。如果您要键入 [1,2,3].each{Integer i-> ...} 等。基本上,当它与持久性 ID 相关时(包括适用的方法 sigs 和参数转换)。否则为你喜欢的整数或def。
    • 唐,是的,很高兴知道 re:自动转换参数。定义一个 id 列是无关紧要的,Grails 会为您注入一个 Long id,并且内存中的 GORM 实现将在 2.0 中完全中性您的 @Mock'd 域,除非您的 id 是 Long 类型。所以,故事的寓意是,Long,Long,Long 你的 ids(不用说,像 fooID 这样的引用 FK 必须是 Long)。将属性类型显式映射到遗留数据库存储类型的方法是通过自定义休眠方言,您可以说属性类型 Longs (BIGINT) 应该映射到“mediumint unsigned”并且两端都具有理智;-)
    猜你喜欢
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2022-11-01
    • 2023-04-07
    • 1970-01-01
    • 2021-10-20
    相关资源
    最近更新 更多