【问题标题】:GORM fetch and update in batchesGORM 批量获取和更新
【发布时间】:2020-10-07 12:01:51
【问题描述】:

我需要使用 grails 2.5 更新 Oracle 数据库中大量数据的单个属性

现在我的代码看起来与此类似:

    List booksToUpdate = []
    boolean moreBooks = true
    int offset = 0

    while (moreBooks) {
        def fetchedBooks = []
        if('Europe'){
            fetchedBooks = Book.findAllByAuthorInList(getEuropeanAuthors(),
                    [max: BATCHSIZE, offset: offset])
        } else {
            fetchedBooks = Book.findAllByAuthorInListAndPublishYear(getEnglishAuthors(), '1999',
                    [max: BATCHSIZE, offset: offset])
        }

        booksToUpdate.addAll(fetchedBooks)

        moreBooks = fetchedBooks.size() == BATCHSIZE
        offset += BATCHSIZE
    }

    booksToUpdate.each { book ->
        book.copyright = '2020'
        book.save(flush: true, failOnError: true)
    }

我想批量更新以提高性能。此外,findAll 查询略有不同,最好有条件地建立搜索条件。理想情况下,我想要这样的东西:

    while (moreBooks) {
        def fetchedBooks = []

        def criteria = new DetachedCriteria(Book)
        criteria.build [max: BATCHSIZE, offset: offset] {
            List relevantAuthors = []
            if('Europe') {
                relevantAuthors = getEuropeanAuthors()
                eq 'publishYear', '1999'
            } else {
                relevantAuthors = getEnglishAuthors()
            }
            inList 'author', relevantAuthors
        }
        criteria.updateAll(copyright:'2020') //batch update

        moreBooks = fetchedBooks.size() == BATCHSIZE
        offset += BATCHSIZE
    }

有没有办法做到这一点?不必与 DetachedCriteria 一起使用。我查看了guide,但找不到任何关于传递最大值和偏移量的信息。有没有更好的方法可以在不影响性能的情况下让代码更优雅?

【问题讨论】:

  • 我认为根据常规事实,if('Europe') 将始终评估为 true,因此 else 内部的代码块不会被执行。也许您需要将该值与变量groovy-lang.org/semantics.html#Groovy-Truth的值进行比较
  • 这是伪代码 if('Europe') 代表一些非硬编码条件
  • 好的,我明白了

标签: grails grails-orm criteria hibernate-criteria detachedcriteria


【解决方案1】:

updateAll 会更新所有内容,即使设置了默认的 maxoffset。 我意识到我需要找回更新实例的列表。因此,试图将所有内容强制转换为仅返回 count 的单个 updateAll 是没有意义的。 结束了这个:

List updateCopyright(String geo) {
    DetachedCriteria<Book> findCr = getQueryFromGeo(geo)
    
    List<String> updatedBookIds = []
    boolean moreBooks = true
    int offset = 0
    
    while (moreBooks) {
        List<Book> fetchedBooks = findCr.list([max: BATCHSIZE, offset: offset])
        List currentBatchIds = fetchedBooks*.id

        def updateCr = Book.where {
            inList 'id', currentBatchIds
        }
        int updatedCount = updateCr.updateAll(copyright: '2020')

        moreBooks = updatedCount == BATCHSIZE
        offset += BATCHSIZE

        updatedBookIds.addAll(currentBatchIds)
    }

    updatedBookIds
}


private DetachedCriteria<Book> getQueryFromGeo(String geo) {
    switch (geo) {
        case 'Europe':
            return Book.where {
                author in getEuropeanAuthors()
            }
        case 'England':
            return Book.where {
                author in getEnglishAuthors() &&
                        publishYear == '1999'
            }
        default:
            return Book.where {}
    }
}

还尝试使用createCriteria 有条件地构建我的查询,但可读性受到影响,并且where 查询附带没有编译时检查

【讨论】:

    猜你喜欢
    • 2011-06-29
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多