0

Grails Service中,我必须从 Db 中删除记录,但出现以下错误:

spi.SqlExceptionHelper, Connection is read-only. Queries leading to data modification are not allowed.

虽然@Transactional(readOnly = false)在我的服务中有,但这是我的服务代码中的删除部分:

def adsDurationIs7 = null
adsDurationIs7 = Ads.findAllByDuration("7 days", [sort: "dateCreated", order: "asc"])
adsDurationIs7.each {
   Ads.get(it.id).delete(flush: true)
}
4

2 回答 2

3

我不知道为什么这不起作用,但即使它起作用了,你也在尽可能地昂贵地做这项工作。您将所有实例加载到内存中(包括所有非惰性属性和集合),然后为每个实例获取它id并使用它通过调用再次加载实例get(尽管如果您很幸运和/或您有缓存正确配置这可能是一个无操作),然后使用它一次删除每个数据库记录。而且您正在数据库中订购,这会增加处理时间,但完全没有必要,因为您正在删除查询返回的所有内容。

你真正想要的是 GORM 代码,它最终运行 SQL 类似于

delete from ads where duration=?

其中 PreparedStatement 将?参数值设置为"7 days"

这个“where”查询将完全做到这一点:

Ads.where { duration == '7 days' }.deleteAll()

与此 HQL 更新一样:

Ads.executeUpdate 'delete Ads a where a.duration = :duration',
                  [duration: '7 days']

所以你的服务应该看起来像

import grails.transaction.Transactional

@Transactional
class MyService {

   void deleteAdsDurationIs7() {
      Ads.where { duration == '7 days' }.deleteAll()
   }
}

或者

import grails.transaction.Transactional

@Transactional
class MyService {

   void deleteAdsDurationIs7() {
      Ads.executeUpdate 'delete Ads a where a.duration = :duration',
                        [duration: '7 days']
   }
}
于 2016-01-08T15:08:30.633 回答
0

您正在从控制器的功能执行此服务功能,这不是事务性的。将@Transactional添加到控制器的功能。

这是一个例子: https ://stackoverflow.com/a/21998182/2166188

于 2016-01-08T13:52:12.113 回答