intershop ORMException无法更新 - 刷新ORMObject

时间:2017-08-09 01:01:49

标签: intershop

在集群的intershop环境中,我们看到很多错误消息。我怀疑应用程序服务器之间的通信不可靠。

Caused by: com.intershop.beehive.orm.capi.common.ORMException: 
Could not UPDATE object: com.intershop.beehive.bts.internal.orderprocess.basket.BasketPO

是否有安全的方法为本地应用程序服务器加载最新的实例。

   BasketPO basket = null;
        try{
            BasketPOFactory factory = (BasketPOFactory) NamingMgr.getInstance().lookupFactory(BasketPOFactory.FACTORY_NAME);
            try(ORMObjectCollection<BasketPO>baskets = factory.getObjectsBySQLWhere("uuid=?", new Object[]{basketID},CacheMode.NO_CACHING);){
                if(null != baskets && !baskets.isEmpty()){
                    basket = baskets.stream().findFirst().get();
                }
            }
        }
        catch(Throwable t){
            Logger.error(this, t.getMessage(),t);
        }

ORMObject#refresh方法有帮助吗?

    try{
        if(null != basket)
              basket.refresh();
    }
    catch(Throwable t){
        Logger.error(this, t.getMessage(),t);
    }

3 个答案:

答案 0 :(得分:1)

您遇到此错误,因为乐观锁定“失败”。为了更好地理解这个问题,我将尝试解释乐观锁定在Intershop ORM层中的工作原理。

PO表中有一个名为OCA的列(OCA ==乐观控制属性?)。想象一下,两个服务器(或两个不同的线程/事务)尝试更新表中的同一行。出于性能原因,默认情况下不涉及DB锁定(例如,通过发出select for update)。相反,第一个线程/服务器在其事务中成功更新行时将OCA递增1。

第二个线程/服务器从创建自己的状态时就知道OCA的值。然后它尝试通过发出类似的查询来更新行:

UPDATE ... OCA = OCA + 1 ... WHERE UUID = <uuid> AND OCA = <old_oca>

由于OCA已经被第一个线程/服务器递增,因此更新失败(实际上 - 更新0行),并且当ORM层检测到没有更新行时,抛出上面发布的异常。

您的问题不是服务器间通信,而是以下事实:

  • 多个服务器/线程尝试更新同一个对象;
  • 数据库中存在绕过ORM层的直接更新(不太可能);

要解决此问题,您可以:

  1. 完全避免这种情况(我强烈推荐:-));
  2. 使用ISH锁定框架(非常繁琐的imHo);
  3. 使用ISH ORM层和Oracle支持的pesimistic锁定(注意潜在的性能问题,死锁,错误);
  4. 使用Java锁定 - 但由于服务器在不同的JVM-s中运行,因此这很少是一个选项;
  5. OFFTOPIC备注:我不知道为什么在知道主键(uuid)时使用getObjectsBySQLWhere。据我记得ORMObjectCollection - 如果没有完全迭代,应该关闭。

    更新:如果未正确配置群集并且无法从节点接收多播,则无法以编程方式解决问题。

答案 1 :(得分:0)

&#34; ORMObject.refresh()&#34;将缓存的共享状态标记为无效。下一次访问该对象将从数据库重新加载该状态。这会影响性能并增加数据库服务器负载。

BUT: &#34;刷新()&#34;如果PO实例状态已分配给当前事务,则不会重新加载PO实例状态。

最好调查并修复服务器通信问题。

答案 2 :(得分:0)

其他可能性是它不是通信问题(我假设集群中的节点之间的多播),但是只有两个请求同时尝试更新篮子。示例二ajax请求更新篮子上的内容。

我会避免尝试&#34;修复&#34;在这个问题上,它只会造成弊大于利。而是进一步调查并发回更多信息。