2010-10-01 59 views
4

我想知道从数据库中的某一行更新域类中的单个值的最有效方法。可以说域名类有20+字段Grails:更新域中的单个对象,“.save”Vs“.executeUpdate”

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) 

回答

7

如果未更新字段的大小和数量很大(这是主观的),则executeUpdate更有效。这也是我经常删除实例的原因,运行'从Foo删除id = 123',因为我完全加载实例只是为了调用delete(),这似乎很浪费。

如果您的域类中有大字符串并使用get()和save()方法,那么当需要更改的所有字段都是不必要时,将所有数据从数据库序列化到Web服务器两次。

如果您正在使用它(如果您编辑的实例很多,您可能不应该这样做),则需要考虑对二级缓存的影响。使用executeUpdate,它将刷新所有先前使用get()加载的实例,但是如果使用get + save更新,则只刷新一个实例。如果你是集群化的,那么这会变得更糟,因为在executeUpdate之后,你将清除所有不同的集群节点缓存,同时清除所有节点上的一个实例。

最好的选择是基准两种方法。如果你没有超载数据库,那么你可能会过早地进行优化,并且在解决其他问题时使用标准方法可能会让事情变得简单。

3

我认为他们是平等的。这两个问题2 sql调用。

更有效的将只是一个单一的更新

Item.executeUpdate("update Item set itemUsage=itemUsage+1 where id =(:itemId)", [ itemId: itemId.id]) 
4

如果使用get/save,你会得到休眠缓存的最大优势。 executeUpdate可能会强制更多的选择和更新。

executeUpdate与hibernate缓存交互的方式在这里有所不同。休眠缓存在executeUpdate上失效。该项目在executeUpdate后的下一个访问将去数据库(可能更多,我认为休眠可能会使缓存中的所有项无效)。

最好的办法是打开Config.groovy中'org.hibernate'的调试日志并检查SQL调用。