今天在看分布式事務(wù)的時(shí)候,突然收到app不能簽到的消息嘴瓤,趕緊解決扫外。
具體解決方法:
1、把執(zhí)行錯(cuò)誤的處理方法提取出來(lái)廓脆,作為測(cè)試方法
2筛谚、這個(gè)方法里面有兩個(gè)插入語(yǔ)句,一條查詢語(yǔ)句停忿,一個(gè)更新語(yǔ)句驾讲,涉及到三張表。
3席赂、報(bào)錯(cuò)信息為
"nested exception is org.apache.ibatis.exceptions.PersistenceException: \n### Error committing transaction. Cause: java.lang.NullPointerException: Can't serialize null\n### Cause: java.lang.NullPointerException: Can't serialize null
4吮铭、今天只是為了做集群,將Mybatis的緩存由默認(rèn)的內(nèi)存緩存改為了Memcached颅停,突然就報(bào)這個(gè)錯(cuò)谓晌。
思路
- 插入語(yǔ)句一般不會(huì)緩存,只有Select語(yǔ)句才會(huì)緩存便监。不能持久化扎谎,我只用了一個(gè)選擇語(yǔ)句,這個(gè)語(yǔ)句是執(zhí)行正常的啊烧董,查看日志毁靶,發(fā)現(xiàn)問(wèn)題。
Flushing keys: [_mybatis_22a025828e62efbe0adda93d10f748e15fe8cecd]
Flushing group: _mybatis_2610d3ffc622c90f08b859a4e787189c9230d66e
- 每次插入或更新語(yǔ)句的時(shí)候都會(huì)Flush cache逊移,導(dǎo)致剛查詢的緩存結(jié)果為清空预吆,因?yàn)榧恿耸聞?wù)注解,所以等方法執(zhí)行完畢的時(shí)候胳泉,緩存為null拐叉,然后報(bào)錯(cuò)。
教訓(xùn)
在事務(wù)處理的時(shí)候扇商,如果是使用Memcache做緩存凤瘦,盡量不要把Select語(yǔ)句和Insert語(yǔ)句放到一起。
如果是使用Redis作為Mybatis的緩存案铺,則未發(fā)現(xiàn)問(wèn)題蔬芥。
額外
Mybatis二級(jí)緩存的擴(kuò)展包中文件數(shù)量較少,并且官方的Mybatis-Redis直接使用,當(dāng)前版本也會(huì)報(bào)錯(cuò)笔诵,無(wú)法集成返吻。
解決方案:
-
將所有Mybatis-redis擴(kuò)展包拷貝到當(dāng)前項(xiàng)目
二級(jí)緩存包中文件 修改Rediscache的構(gòu)建方法
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(),
redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(),
redisConfig.getDatabase(), redisConfig.getClientName(),false,null,null,null);
}
- 可以使用Redis作為Mybatis的二級(jí)緩存,在Mybatis全局配置與Mapper文件中配置好即可乎婿。
集成Mybatis-Memecache也類似测僵,可以拷貝二級(jí)緩存包內(nèi)容,進(jìn)行擴(kuò)展