我想知道从数据库中的一行更新域类中的单个值的最有效方法是什么。可以说域类有20多个字段
def itemId = 1
def item = Item.get(itemId)
itemId.itemUsage += 1
Item.executeUpdate("update Item set itemUsage=(:itemUsage) where id =(:itemId)", [usageCount: itemId.itemUsage, itemId: itemId.id])
vs
def item = Item.get(itemId)
itemId.itemUsage += 1
itemId.save(flush:true)
答案 0 :(得分:7)
executeUpdate更有效。这也是我经常删除实例的方式,运行'从Foo删除id = 123',因为看起来完全加载实例只是为了调用它上面的delete()似乎很浪费。
如果您的域类中有大字符串并使用get()和save()方法,那么当您需要更改的所有字段都是一个字段时,您将所有这些数据从数据库序列化到Web服务器两次。 / p>
如果您正在使用它,则需要考虑对二级缓存的影响(如果您编辑很多实例,则可能不应该这样做)。使用executeUpdate,它将刷新之前使用get()加载的所有实例,但如果使用get + save进行更新,则只刷新该实例。如果你是集群的话会变得更糟,因为在执行executeUpdate之后,你要清除所有各种集群节点缓存,而不是刷新所有节点上的一个实例。
您最好的选择是对两种方法进行基准测试。如果您没有超载数据库,那么您可能会过早地进行优化,使用标准方法可能最好在解决其他问题时保持简单。
答案 1 :(得分:4)
如果您使用get
/ save
,您将获得hibernate缓存的最大优势。 executeUpdate
可能会强制进行更多选择和更新。
executeUpdate
与hibernate缓存交互的方式在这里有所不同。 hibernate缓存在executeUpdate
上失效。在executeUpdate之后,该项的下一次访问将有转到数据库(可能更多,我认为hibernate可能会使缓存中的所有项无效)。
最好的办法是在Config.groovy中启用'org.hibernate'的调试日志记录,并检查SQL调用。
答案 2 :(得分:3)
我认为他们是平等的。两者都发出2个sql调用。
效率更高只是一次更新
Item.executeUpdate("update Item set itemUsage=itemUsage+1 where id =(:itemId)", [ itemId: itemId.id])
答案 3 :(得分:1)
您可以在Item类中使用dynamicUpdate mapping属性:
http://grails.org/doc/latest/ref/Database%20Mapping/dynamicUpdate.html
启用此选项后,使用Gorm更新单个字段的第二种方法将与第一种方式一样高效。