【问题标题】:findBy appear to update the databasefindBy 出现更新数据库
【发布时间】:2015-01-09 10:20:51
【问题描述】:

我有以下代码:

println "@@@@@@@@ RUNNING ProfessionaCustomer - ${pcCounter} under ${accountCustomer.customerNumber}  Professional SQLid ${it.id}"
def professionalCustomerId = it.customerId
def professionalCustomer = ProfessionalCustomer.findByCustomerNumber(professionalCustomerId)

我有 SQL 登录,我得到:

@@@@@@@@ RUNNING ProfessionaCustomer - 31 under 106450  Professional SQLid 100759
Hibernate: update base_domain set version=?, account_name=?, address_line1=?,  address_line2=?, city=?, customer_number=?, date_created=?, disabled=?, last_updated=?, postal_code=?, primary_phone=?, state_or_province=? where id=? and version=?
Hibernate: update base_domain set version=?, address1=?, address2=?, city=?, customer_number=?, date_created=?, disabled=?, first_name=?, last_name=?, last_updated=?, middle_name=?, phone_number=?, postal_code=?, state=? where id=? and version=?
Hibernate: insert into account_customer_professionals (account_customer_id, professional_customer_id) values (?, ?)
Hibernate: select this_.id as id1_3_0_, this_.version as version2_3_0_, this_.address1 as address70_3_0_, this_.address2 as address71_3_0_, this_.city as city7_3_0_, this_.customer_number as customer8_3_0_, this_.date_created as date_cre9_3_0_, this_.disabled as disable10_3_0_, this_.first_name as first_n19_3_0_, this_.last_name as last_na20_3_0_, this_.last_updated as last_up11_3_0_, this_.middle_name as middle_72_3_0_, this_.phone_number as phone_n73_3_0_, this_.postal_code as postal_12_3_0_, this_.state as state74_3_0_ from base_domain this_ where this_.class='com.eveo.nplate.model.ProfessionalCustomer' and this_.customer_number=? limit ?

正在更新数据库。这可以解释为什么速度如此之慢,但我看不出有任何原因发生这种情况。

为什么“findBy”会导致更新?

【问题讨论】:

    标签: performance grails findby


    【解决方案1】:

    Hibernate 不会立即执行创建、更新或删除,直到它认为它必须这样做 - 它会尽可能地等待(尽管它相当悲观),并且只会在你告诉它时或它认为它时刷新这些更改需要。一般来说,唯一一次在没有显式调用的情况下刷新是在运行查询时。这是因为内存中的任何新实例、更新实例和已删除实例(缓存在 Hibernate Session 中,1st 级缓存)都可能影响查询结果,因此它们必须刷新到数据库,以便您获得正确的查询结果。

    对此的一个例外是在新实例上调用save()。 Grails 会刷新这一点,因为通常 id 是由数据库分配的,通​​过自动增量列或序列。为了确保内存中的状态与数据库相同,它会刷新save() 调用,以便它可以检索 id 并将其设置在实例中。但是,如果您检索持久性实例(例如,使用 get() 调用,或使用条件查询、查找器等)并对其进行修改,则在其上调用 save() 不会自动刷新。 delete() 调用也是如此 - 未刷新。

    delete()save() 对持久实例的调用视为向Hibernate 发送的消息,表明该操作应“最终”执行。

    因此,当您执行查找器、条件、“位置”或 HQL 查询时,Hibernate 将为您刷新所有未刷新的更改。如果您不希望这种情况发生(例如在自定义域类验证器闭包中),您可以在单独的会话中运行查询,例如使用withNewSession 方法。

    如果您根本不刷新会话,无论是在Session 实例上显式地或通过将flush:true 添加到savedelete 调用,会话将被刷新,因为 Grails 注册了一个 OpenSessionInView在每个请求开始时启动会话并在结束时刷新和关闭它的拦截器。这有助于延迟加载;由于有一个会话打开并绑定到已知位置的ThreadLocal,Hibernate 和 GORM(通过 Spring 的HibernateTemplate)可以使用该打开的会话在查询运行后按需检索延迟加载的集合和实例。

    另请注意,您不需要在事务中刷新。事务管理器是一个 Spring HibernateTransactionManager,在提交之前刷新。

    【讨论】:

      【解决方案2】:

      可能会话中的某些事务未保存在数据库中。

      当您运行findBy 时,hibernate 会利用连接来运行这两个查询。我相信这就是发生的事情。

      【讨论】:

      • 维克多,非常感谢您的意见。当然 - 现在很清楚了。
      猜你喜欢
      • 2021-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-02
      • 2017-01-16
      • 2017-09-11
      • 2020-09-18
      • 1970-01-01
      相关资源
      最近更新 更多