作者:cndz 围观群众:755 更新于 标签:springboot双数据源mybaits_plusspringboot双数据源报错
项目配置:springboot + mybatisPlus + 双数据源
1.最近给一个项目增加了某些功能,需要配置双数据源。结果发现在调用mybatis_plus的 saveBatch
或者 batchSave
方法的时候报错,报错信息如下:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: springTransactionManager,otherTransactionManager
问题产生的原因呢,其实看下下面代码就知道了。
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
sqlSession.insert(sqlStatement, entity);
});
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveOrUpdate(T entity) {
if (null == entity) {
return false;
} else {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
}
}
}
原来mybatis_plus ServiceImpl
的saveBatch
和 saveOrUpdate
方法默认使用了。 @Transactional注解,在多数据源的情况下,使用 @Transactional需要指定 transactionManager。否则就会报开头的错误信息。
其实解决办法很简单,在自己的service中重写自己用到的方法即可。
public class DemoService extends ServiceImpl<DemoDao, Demo> implements DemoServiceImpl {
@Override
@Transactional(
transactionManager = "springTransactionManager",
rollbackFor = {Exception.class}
)
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
sqlSession.insert(sqlStatement, entity);
});
}
@Override
@Transactional(
transactionManager = "springTransactionManager",
rollbackFor = {Exception.class}
)
public boolean saveOrUpdate(T entity) {
if (null == entity) {
return false;
} else {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
}
}
//其他业务逻辑。
}
其实需要注意的只有两点,配置双数据源使用 @Transcactional注解需要指定transactionManager
。需要额外注意的是系统类似于MybatisPlus中的某些方法上的注解容易被忽略。解决办法呢就是重写需要用到的方法。当然,saveOrUpdate
saveBatch
方法只是举个例子。其他 @Transcactional在双数据源的使用场景下同样需要重写。