【问题标题】:grails delete all data from table / domain class, i.e. "deleteAll"grails 从表/域类中删除所有数据,即“deleteAll”
【发布时间】:2023-03-10 02:57:01
【问题描述】:

我有一个域类 Widget,我需要从中删除所有实例——清除它。之后,我将加载新数据。您建议采用什么机制来做到这一点?

附:请注意,这不是在引导时,而是在“运行时”。

【问题讨论】:

标签: grails grails-orm


【解决方案1】:

最简单的方法是直接使用HQL:

DomainClass.executeUpdate('delete from DomainClass')

【讨论】:

  • 太好了,谢谢,这工作非常快。 (与此无关 - 关于为什么过滤器在过滤器/拆分线问题中对我不起作用的任何想法?它对您有用吗?)
  • 这适用于最新版本的 Grails。在 2.4.4 中还没有。
  • @ataylor 如果域类有关联怎么办?通常,我们希望删除所有这些,而不仅仅是这个 DomainClass
【解决方案2】:
DomainClass.findAll().each { it.delete() }

如果您想避免任何 GORM 陷阱,例如需要立即删除对象并检查以确保它确实被删除,请添加一些参数。

DomainClass.findAll().each { it.delete(flush:true, failOnError:true) }

【讨论】:

  • 请注意,这会将整个集合从数据库加载到内存中,然后单独删除每个集合,每个集合都有单独的数据库查询。如果您要删除的对象不止几个,由于到数据库的往返次数,这样做的性能将会很糟糕。
【解决方案3】:

相当老的帖子,但仍然是真实的。

如果您的表非常大(数百万个条目),使用 findall()*.delete() 进行迭代可能不是最佳选择,因为您可能会遇到事务超时(例如 MySQL innodb_lock_wait_timeout 设置),除了说明的潜在内存问题作者:GreenGiant。

所以至少对于 MySQL Innodb,使用 TRUNCATE TABLE 更快:

sessionFactory.currentSession
  .createSQLQuery("truncate table ${sessionFactory.getClassMetadata(MyDomainClass).tableName}")
  .executeUpdate()

这仅在您的表未被其他对象作为外键引用时才有用。

【讨论】:

    【解决方案4】:

    据我所知,我同意@ataylor 如果您的域对象中没有关联(在任何实际应用程序中极不可能),则以下代码是最快的:

    DomainClass.executeUpdate('delete from DomainClass')
    

    但是,如果您与其他域有关联,那么最安全的删除方法(也比上面提到的要慢一点)如下:

    def domainObjects = DomainClass.findAll()
    domainObjects.each { 
    it.delete(flush:it==domainObjects.last, failOnError:true) 
    }
    

    【讨论】:

      【解决方案5】:

      如果你有一个对象列表并且想要删除所有元素,你可以使用*操作符。

      '*' will split the list and pass its elements as separate arguments.
      

      示例。

      List<Book> books = Book.findAllByTitle('grails')
      books*.delete()
      

      【讨论】:

        猜你喜欢
        • 2017-08-21
        • 1970-01-01
        • 1970-01-01
        • 2017-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多