杂七杂八bug(持续更新)
2022.1.17
1.数据库抛出异常后端catch SQLException接不到
数据库unique key冲突报错,日志中显示为
SQLIntegrityConstraintViolationException
但是使用catch这个异常和SQLException会接不住,debug查下去发现抛出的是
RuntimeException
2022.1.19
2.Mybatis-plus不支持双主键
项目用到了RabbitMQ去同步组织架构的数据库,在接收方接收到数据时会做一个insert,分多条记录当前部门对应的上级链,数据库里面设置了双主键,代码里使用的saveOrUpdate。代码原作者可能是想利用双主键进行更新,但是没料到mp只支持单主键的CRUD。
/**
* TableId 注解存在更新记录,否插入一条记录
*
* @param entity 实体对象
* @return boolean
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveOrUpdate(T entity) {
if (null != entity) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity);
}
return false;
}
从源代码可以看见最后saveOrUpdate方法中会用
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
default T getById(Serializable id) {
return getBaseMapper().selectById(id);
}
来判断是更新还是插入,继续往下翻
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
public T selectById(Serializable id) {
SqlSession sqlSession = sqlSession();
try {
return sqlSession.selectOne(sqlStatement(SqlMethod.SELECT_BY_ID), id);
} finally {
closeSqlSession(sqlSession);
}
}
SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s} %s")
%s是sql参数化,但是我们在代码里没有定义主键标签,所以这里取的应该是第一个字段。
这样的话其实只有第一次是save,其余情况下判断当前id有数据,走的都是update