如何维护EntityManager';JBoss下的Hibernate缓存是否处于一致状态?

如何维护EntityManager';JBoss下的Hibernate缓存是否处于一致状态?,hibernate,caching,jboss,entitymanager,Hibernate,Caching,Jboss,Entitymanager,我们正在使用Hibernate运行JBoss,并且遇到了这个问题 当会话bean使用EntityManager查找实体时,它可能已经存在于EntityManager的缓存中,并且其状态可能已经过时。如果代码使用这样的实体进行决策,它可能会做出错误的决策,从而产生bug 下面是一个例子 HTTP请求1。会话bean创建一个实体实例,并使用字段“A”将其存储为值1。持久化实体获取ID=4 HTTP请求2。会话bean查找ID=4的实体,将其字段“A”设置为值2并保存它 HTTP请求3。会话bean查

我们正在使用Hibernate运行JBoss,并且遇到了这个问题

当会话bean使用EntityManager查找实体时,它可能已经存在于EntityManager的缓存中,并且其状态可能已经过时。如果代码使用这样的实体进行决策,它可能会做出错误的决策,从而产生bug

下面是一个例子

HTTP请求1。会话bean创建一个实体实例,并使用字段“A”将其存储为值1。持久化实体获取ID=4

HTTP请求2。会话bean查找ID=4的实体,将其字段“A”设置为值2并保存它

HTTP请求3。会话bean查找ID=4的实体并检查其字段“A”。如果值为1,它做一件事,如果值为2,它做另一件事

如果请求3中的EM恰好与请求1中的EM相同,则会发生意外行为。我对此进行了测试,得到了大约10%的失败案例

所以问题是——如何避免这种情况?每次调用em.refresh()或em.clear()以确保实体是最新的,这似乎是在浪费资源。

Artem

这似乎是您的问题之一:-)

虽然我知道你以前得到的答案(包括我的答案)可能不是你所希望的,但它们不会改变:

  • 实体管理器是映射到Hibernate会话的,通常需要是短期的。这篇文章很好地解释了与Hibernate会话相关的工作单元、事务和范围,如果您以前没有看过,请看一看 如果你的应用程序始终坚持实体管理者,你需要认真考虑改变这种策略;如果您只是在一些确实需要进行长事务的地方执行此操作,而不是使用
    refresh()
    方法,那么肯定会有较小的缺点
  • 与具有群集实现的不同,会话级缓存在不同的会话(实体管理器)之间不同步(按设计),对同一实体的并发更新通过Hibernate或应用程序级锁定进行处理
  • 理论上,你可以(只要你的ORM访问被很好地分开)维护你自己的缓存(如果需要的话,集群化的)由不同的实体管理者持有的实体;您需要向每个服务器注册相应的服务器,以保持缓存同步。不过,我强烈建议不要使用这种方法,因为它不仅需要大量的实现,而且容易出现错误,而且这与Hibernate的范例背道而驰
Artem

这似乎是您的问题之一:-)

虽然我知道你以前得到的答案(包括我的答案)可能不是你所希望的,但它们不会改变:

  • 实体管理器是映射到Hibernate会话的,通常需要是短期的。这篇文章很好地解释了与Hibernate会话相关的工作单元、事务和范围,如果您以前没有看过,请看一看 如果你的应用程序始终坚持实体管理者,你需要认真考虑改变这种策略;如果您只是在一些确实需要进行长事务的地方执行此操作,而不是使用
    refresh()
    方法,那么肯定会有较小的缺点
  • 与具有群集实现的不同,会话级缓存在不同的会话(实体管理器)之间不同步(按设计),对同一实体的并发更新通过Hibernate或应用程序级锁定进行处理
  • 理论上,你可以(只要你的ORM访问被很好地分开)维护你自己的缓存(如果需要的话,集群化的)由不同的实体管理者持有的实体;您需要向每个服务器注册相应的服务器,以保持缓存同步。不过,我强烈建议不要使用这种方法,因为它不仅需要大量的实现,而且容易出现错误,而且这与Hibernate的范例背道而驰

感谢您的耐心和帮助。我意识到我一直在问错误的问题。这是我真正想要的。很抱歉,我是个白痴。你的问题一点也不愚蠢-整个会话缓存的事情都很混乱:-)我在上面的问题中留下了一条评论,也许会有所帮助-我自己没有使用CMP,所以我不太确定如何更改实体管理器范围;不过,这肯定是一个配置/部署问题-我相信有人会回答您的问题。祝您实施顺利。感谢您的耐心和帮助。我意识到我一直在问错误的问题。这是我真正想要的。很抱歉,我是个白痴。你的问题一点也不愚蠢-整个会话缓存的事情都很混乱:-)我在上面的问题中留下了一条评论,也许会有所帮助-我自己没有使用CMP,所以我不太确定如何更改实体管理器范围;不过,这肯定是一个配置/部署问题-我相信有人会回答您的问题。祝您的实现好运。