【问题标题】:Grails performance issue with fields plugin字段插件的 Grails 性能问题
【发布时间】:2014-01-09 08:06:43
【问题描述】:

我的 Grails 应用程序出现性能问题。我正在使用fields plugin 来渲染我的“创建”、“编辑”和“显示”脚手架视图,但是当我的开发数据库中有大量数据时,渲染页面的时间就会飞速发展。

我在字段插件的FormFieldsTagLib.buildModel 方法中追踪到这一行:

def value = attrs.containsKey('value') ? attrs.remove('value') : propertyAccessor.value

看起来当propertyAccessor.value 引用一个包含许多实体的集合时(在我的数据库中,我有一个可能有大约 30000 行的集合),此时它们都被获取了。这似乎有点浪费,因为 _field.gsp 片段可能最终不会对该值做任何事情。

首先,有没有其他人遇到过这个问题?

如果不是,那可能是我在使用字段插件时出了点问题?

另外,我突然想到,当调用myDomainObject.myCollection 时,也许有一种方法可以让 gorm/hibernate 仅将集合中的前 n 个项目加载到内存中,但经过一番谷歌搜索后,它看起来好像不可能。

编辑:

我正在使用 Grails 2.2.2 和 Fields 插件 1.3

【问题讨论】:

  • 您的视图需要显示这种关系?全部加载不是一个好主意,通常您使用分页来完成。
  • 我真的不想在我的页面上显示这种关系——我已经为此属性创建了一个“空白”_field.gsp,以便字段插件不呈现任何内容。但是,当在我的脚手架 show/edit/create gsp 中使用 f:all 时,字段 taglib 会迭代我的域对象的每个属性并在其上调用“propertyAccessor.value”。这对于大多数属性来说都不是问题,但是当属性是一个相当大的集合时,它会有点问题:-)
  • The docs 说你可以定义一个不会被处理的属性列表(参见'except'属性)。
  • 谢谢 - 我认为这会起作用。不过,我将尝试覆盖“buildModel”方法-当我可以访问bean和propertyName时,我认为没有必要将值放入属性映射中

标签: grails


【解决方案1】:

我通过像这样修改FormFieldsTagLib.buildModel 方法解决了这个问题:

    private Map buildModel(BeanPropertyAccessor propertyAccessor, Map attrs) {
            //def value = attrs.containsKey('value') ? attrs.remove('value') : propertyAccessor.value
            def valueDefault = attrs.remove('default')
            [
                    bean: propertyAccessor.rootBean,
                    property: propertyAccessor.pathFromRoot,
                    type: propertyAccessor.propertyType,
                    beanClass: propertyAccessor.beanClass,
                    label: resolveLabelText(propertyAccessor, attrs),
                    //value: (value instanceof Number || value instanceof Boolean || value) ? value : valueDefault,
                    constraints: propertyAccessor.constraints,
                    persistentProperty: propertyAccessor.persistentProperty,
                    errors: propertyAccessor.errors.collect { message(error: it) },
                    required: attrs.containsKey("required") ? Boolean.valueOf(attrs.remove('required')) : propertyAccessor.required,
                    invalid: attrs.containsKey("invalid") ? Boolean.valueOf(attrs.remove('invalid')) : propertyAccessor.invalid,
                    prefix: resolvePrefix(attrs.remove('prefix')),
            ]
    }

现在我已经从模型中删除了 value 属性,我必须像这样在每个 _field.gsp 中获取我的属性值:

${bean."${propertyName}"}

但我认为在处理大型集合时,为了获得更好的性能付出的代价很小。

【讨论】:

    【解决方案2】:

    这不是插件的问题,是数据模型问题,需要通过建模问题来解决。

    您的收藏似乎被急切地获取,您应该首先验证这一点,请参阅Docs on lazy & eager fetching

    您所说的“内存中的第 n 个项目”称为 batch fetching 并按 n 成员组加载行

    你也可以让你的页面显示这个字段,如commented by @Sérgio Michels

    【讨论】:

    • 嗨,Grooveek,我的收藏并没有被抢购一空。当我加载封闭实体时,此时未加载我的集合。仅在调用 entity.myCollection 时。
    • 好的。众所周知,集合是 Grails 应用程序中的性能杀手。我们完全删除了它们(我们有引用数千个其他行的行)。想走这条路的可以看this inspiring talk
    • 啊,我确实看过那个演讲。他是个聪明的小伙子,贝克威斯先生 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 2016-06-28
    • 1970-01-01
    相关资源
    最近更新 更多