我注意到Wildfly 10上的一个奇怪的问题在weblogic中没有出现。
总之,在wildfly中,我遇到了一个观察事件@ApplicationScoped
事件的@Observes(during = TransactionPhase.AFTER_SUCCESS) SomeEvent
bean,并且在其观察逻辑中使用@EJB
来打开一个新鲜的小型事务上下文,正在访问由发布事件的原始@Mdb
事务修改的陈旧实体。
这种“单线程”现象可能导致多个有趣的例外。
错误类型1:乐观锁异常:
如果您的AFTER_SUCCESS
观察者希望自己运行一个简短的事务,该事务修改发布事件的主要事务的实体。
嗯 - 在第一次尝试时,您会获得乐观的锁定异常。
你得到它是因为即使MDB在Thread1上运行它的事务,并且你的串行观察者在Thread 1上成功后观察。
您遇到的问题是,如果您检查这些更改,MDB会成功将更改提交到数据库,但您观察者正在从实体管理器加载实体,就好像它已过时,处于Mdb运行之前的状态。
所以@versioninfo
只是陈旧而Eclipselink认为你有一个乐观的锁定异常。
如果允许乐观锁定异常发生并再次重试以在同一个Thread1上运行事务,则可以解决问题并设法完成更改。
这是邋and和丑陋但它的确有效。
第二类问题更为严重。
如果成功的@bserver
执行了只读事务,那么没有任何事情发生,并且您没有任何迹象表明您正在使用陈旧数据。
这很糟糕,非常糟糕。
所以在这里我尝试用我的观察者做类似的事情。
MyEntity entity = em.fetchById(primaryKeyOfEntity);
String staleValue = entity.getFieldModifiedByMdbTransaction();
em.refreh(rentity);
String secondTryToGetTheValue = entity.getFieldModifiedByMdbTransaction();
// now the value is no longer stale it is perfect. It is what the MDB that published the event committed.
在weblogic 12.2.1.2上使用相同的eclipselink版本,@Observing ON_SUCCESS
的模式不会返回任何陈旧数据。
对第一个Mdb事务所做的更改很好地发布到在同一个线程上运行的ON_SUCCESS
事务。
有人意识到这一点吗?
有没有办法告诉实体经理它应该使用服务器会话缓存而不是本地缓存?
可能是EclipselInk仅在处理事件ON_SUCCESS之后将修改实体的工作单元缓存移动到服务器缓存而不是onCommit()
?意思是,服务器会话缓存持有过时的实体,直到ON_SUCCESS
完成? - 这不应该。当向DB发出提交并且在调用ON_SUCCESS
之前,必须将工作单元缓存发布到会话缓存。
然而,ON_SUCCESS
确实在@TransactionAttribute(RequriesNew)
上,当它启动时应该有一个空的工作单元。
此外,我尝试entitManager.clear()
,它没有效果。
唯一可以解决非陈旧实体的问题是em.refresh()
。
对我来说em.refresh()
总是闻起来像是草率的代码。
其他人在野生蝇身上遇到过同样的问题吗? 任何神奇的eclipselink持久性单元属性可以在不破坏性能的情况下解决这个问题吗?