1

我有以下代码:

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”会导致更新?

4

2 回答 2

2

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

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

delete()将持久实例视为并调用Hibernatesave()的消息,表明该操作应该“最终”执行。

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

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

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

于 2015-01-11T03:40:59.957 回答
1

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

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

于 2015-01-09T10:36:07.140 回答