Activiti缓存机制解析

本文探讨了Activiti的DbSqlSession在事务处理中的角色,详细阐述了insert、delete和update操作如何与缓存配合。Activiti的update操作需要先查询对象并更新属性,然后在flush时对比状态来决定是否执行数据库更新。对于不直接通过对象属性更新的情况,建议先通过select确保数据在缓存中,然后强制更新PersistentState。同时,文章提到Activiti默认不使用Mybatis的缓存,但在复杂业务场景下,可以考虑结合Mybatis的缓存机制以提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Activiti的持久化和缓存最终都是有DbSqlSession处理的,在此主要也是讲这个对象。类图如下。

public class DbSqlSession implements PersistenOperation, Session {

    protected SqlSession sqlSession;
    protected List<PersistentObject> insertedObjects = new ArrayList<PersistentObject>();
    protected Map<Class<?>, Map<String, CachedObject>> cachedObjects = new HashMap<Class<?>, Map<String, CachedObject>>();
    protected List<DeleteOperation> deletedObjects = new ArrayList<DeleteOperation>();
}

  首先是insert,这里它使用了一个List对插入对象进行缓存,在通过flush()方法,flush之后最终会使用sqlSession把数据鎚入数据源,sqlSesion是所有对象最终持久化的唯一入口。

delete的作法基本上和inert一样,deltet做多了一层封装DeleteOperation,使用这个对象,适配id进行删除。

 

重点是update,这里update要结合select一起使用。在DbSqlSession对象中,没有update方法,update要求先进行select查询对象,更新查询对象,最终flush()的适合,chched容器会检查最终状态是否和查询时的状态一致,如果不一致,才会进行持久化更新。也就是说,用户只需要查询出对象,使用对象的set方法,更新属性,这样子就会默认进行更新了。在实现的适合注意getPersistentState()的实现,也就是说,会使用到属性更新的属性,需要够着一个判断状态更新的对象让cache容器对比。

flush()的时候,cache容器会先清理掉insert对象和delete对象。

我们看看CachedObject对象的设计。

 

public static class CachedObject {
        protected PersistentObject persistentObject;
        protected Object persistentObjectState;

        public CachedObject(PersistentObject persistentObject, boolean storeState) {
            this.persistentObject = persistentObject;
            if (storeState) {
                this.persistentObjectState = persistentObject.getPersistentState();
            }
        }

        public PersistentObject getPersistentObject() {
            return persistentObject;
        }

        public Object getPersistentObjectState() {
            return persistentObjectState;
        }
    }

 

  这里可以看明白我们属性设置对比和最终持久。当查询的适合,用storeState = true 构造CachedObject, PersistentState会被保存在对象中。外部API通过select对象的引用更新属性,flush()的适合,会拿最终对象的PersistentState与select出来的对象进行对比,如果不一致,就update数据源记录。代码如下。

 

 public List<PersistentObject> getUpdatedObjects() {
        List<PersistentObject> updatedObjects = new ArrayList<PersistentObject>();
        for (Class<?> clazz : cachedObjects.keySet()) {
            Map<String, CachedObject> classCache = cachedObjects.get(clazz);
            for (CachedObject cachedObject : classCache.values()) {
                PersistentObject persistentObject = cachedObject.getPersistentObject();
                if (!deletedObjects.contains(persistentObject)) {
                    Object originalState = cachedObject.getPersistentObjectState();
                    if (!originalState.equals(persistentObject.getPersistentState())) {
                        updatedObjects.add(persistentObject);
                    } else {
                        log.finest("loaded object '" + persistentObject + "' was not updated");
                    }
                }
            }
        }
        return updatedObjects;
    }

 

 

到这里,我遇到了一个问题,如果我不使用对象属性更新,也想update数据源记录,显然activiti这一套实现机制是不支持的,那怎么办呢?我的解决办法如下。

 

/**
     * 更新数据,对源码的扩展。
     * 一般的更新是直接通过Entity对象属性设置。此处暴露出一种直接更新对象的方法。
     * 
     * @param persistentObject
     */
    public void update(PersistentObject persistentObject) {
        PersistentObject oldPersistentObject = selectById(persistentObject.getClass(), persistentObject.getId());
        
        //先put对象进缓存容器,再讲持久状态回滚,这样flush的时候,会检查到对象状态变化,进而更新对象。
        CachedObject cachedObject = cachePut(persistentObject, false);
        cachedObject.persistentObjectState = oldPersistentObject.getPersistentState();
    }

  先用select,保证数据源中的记录已经缓存在cache容器中,跟着强制更新PersistentState。保证flush()的时候可以检查状态的一致性。

 

 

activiti依赖Mybatis,关于缓存机制,Mybatis还有自身的机制,有自己的一套缓存回收机制。activiti默认是不适用Mybatis的缓存的,activiti自身的缓存机制够简单,如果在自身command机制里面适用,性能很高,如果是比较复杂的业务场景,会在结合外部扩展适用的话,很可能就不够用了。所有个人认为可以考虑结合Mybatis的缓存机制,混合适用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值