【问题标题】:Hibernate: session.createQuery and session cacheHibernate:session.createQuery 和会话缓存
【发布时间】:2013-11-25 11:46:58
【问题描述】:

我有什么:

我在我的应用程序中集成了状态模式。这意味着当我改变某个实体的状态时,它可能会引起连锁反应。表示相关实体的状态也可能发生变化,而相关实体的状态也可能会改变,以此类推。

我还使用 Hibernate 对话,这意味着我使用 MANUL 刷新模式。

public void handler() {
  session = beginHibernateConversation(); //open new transaction and new session (if it's needed)
  entity.changeState(session); //call chain reaction
  finishhibernateConversation(session); //manual flush, commit, and if it's needed - close session
}

什么问题:

当我使用手动刷新模式时,仅在 finishhibernateConversation(session) 方法上对 DB 进行所有更改。

我需要在changeState(session) 方法中使用session.createQuery 方法。但我看不到实际的实体状态!因为所有更改都存储在未刷新的会话中,而且session.createQuery 与会话上下文无关。

问题:

如何让session.createQuery考虑session cache

一个小例子:

例如我有Person - Job 关系(one-to-many)。当我将一项工作的状态更改为 full time 时,我需要更新所有其他相关工作(因为人们只能从事一份全职工作)。

所以,我愿意(在人员更新请求内部)

  1. job1.changeState('full time')
  2. [第一种方法内]session.createQuery("from Job where person.id = (:id) state in (:states)")

问题是第二个查询不正确,因为它没有考虑job1已经改变的状态

【问题讨论】:

    标签: java hibernate


    【解决方案1】:

    这里有几个选项,但是对于这个问题没有简单的改变。

    1) 使用FlushMode.AUTO。使用自动刷新,Hibernate 在执行查询之前会刷新以避免此问题。自动刷新和您使用的模式之间不应该有任何冲突,但是自动刷新还有其他问题。通常在高并发环境中,您可能会遇到问题,因为它会保留较长的数据库事务。

    2) 当您进行这样的查询时,请离开根对象并在内存中查询。在此示例中,这类似于获取人员并遍历其 Job 集合。

    3) 创建一个 ThreadLocal 缓存来跟踪您可能查询的内容。这是所有选项中最糟糕的,但有时是必要的。

    【讨论】:

    • 1) 由于对话,我无法使用 FlushMode.AUTO。对话意味着如果用户按下“取消”按钮,所有更改都应还原。 3) 这确实是最坏的情况 2) 但是,请向我解释第二种选择。
    • 自动刷新将在这种情况下工作(它正在刷新到数据库,但它没有提交数据库事务)。它只会导致数据库锁很糟糕,因此不推荐。我对选项二的意思是这样的: for (Job job : person.getJobs()) { if (job.getState().equals(State.SomeValue)) { return job; } } 之类的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 2011-01-02
    • 2010-09-14
    • 2015-03-13
    相关资源
    最近更新 更多