一、报错内容
org.springframework.dao.DataIntegrityViolationException:
### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'tenant_id' cannot be null
### The error may exist in com/xxx/cloud/mall/admin/mapper/GoodsCategoryMapper.java (best guess)
### The error may involve com.xxx.cloud.mall.admin.mapper.GoodsCategoryMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO goods_category (id, enable, parent_id, name, description, sort, create_time, del_flag, tenant_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)
### Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'tenant_id' cannot be null
; Column 'tenant_id' cannot be null; nested exception is java.sql.SQLIntegrityConstraintViolationException: Column 'tenant_id' cannot be null
二、报错说明
Cause: java.sql.SQLIntegrityConstraintViolationException: Column ‘tenant_id’ cannot be null;
报错很明显,就是因为在插入数据表 记录时候,租户字段空了,所以导致了插入失败报错。
INSERT INTO goods_category (
id,
ENABLE,
parent_id,
NAME
description,
sort,
create_time,
del_flag,
tenant_id
)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, NULL)
2.1 为什么本地测试是成功的?
那?为什么本地测试是成功的?发沙箱了就不行了?
因为本机直接跳过了租户的判断,直接到从Gateway转到了Mall-admin
但是沙箱就不行,必需要加上租户字段,才能发起请求。
2.2 能不加租户字段吗?
查看nacos中的配置,发现,我们定义了租户表维护,
其中,刚好操作的这张表(goods_category)是一定要加租户信息的,不然就会报错
base:
# 租户表维护
tenant:
column: tenant_id
tables:
- goods_category
三、报错解决
3.1 【错误尝试】是不是请求Header要加租户字段?
因为是mall-admin,是有页面的,直接发起页面请求之后,Chrome浏览器,点击键盘F12,呼出Chrome的控制台,可以获取到Header中的Token字段(Authorization)+租户字段(switch-tenant-id)
因此,可以直接拷贝到ApiFox中,再次进行接口调用,我还以为解决了,结果问题依旧!
继续排查!
3.2 【正确解决】是不是持久化时,要加tenant_id字段?
认真看一下报错,问题处在GoodsCategoryMapper上,那就在代码前后,往上追溯代码逻辑
The error may exist in com/xxx/cloud/mall/admin/mapper/GoodsCategoryMapper.java
private final JDConfigProperties jDConfigProperties;
@Override
public void saveGoodsCategoryShop(GoodsCategoryImportDTO goodsCategoryImportDTO) {
JSONArray goodsCategoryJsonArray = getJSONArray(goodsCategoryImportDTO);
for (int i = 0; i < goodsCategoryJsonArray.size(); i++) {
// 设置租户ID
TenantContextHolder.setTenantId(jDConfigProperties.getTenantId());
List<GoodsCategoryShop> goodsCategoryShopList = baseMapper.selectList(Wrappers.<GoodsCategoryShop>lambdaQuery()
.eq(GoodsCategoryShop::getId, JSONUtil.parseObj(goodsCategoryJsonArray.get(i)).getStr("id"))
);
//重复类目数据的过滤
if (ObjectUtil.isNotEmpty(goodsCategoryShopList)) {
log.info("重复店铺类目数据:levelOneCategoryId = [{}],导入失败,店铺类目数据记录已经存在", goodsCategoryImportDTO.getLevelOneCategoryId());
continue;
}
GoodsCategoryShop goodsCategoryShop = new GoodsCategoryShop();
goodsCategoryShop.setId(JSONUtil.parseObj(goodsCategoryJsonArray.get(i)).getStr("id"));
goodsCategoryShop.setName(JSONUtil.parseObj(goodsCategoryJsonArray.get(i)).getStr("name"));
goodsCategoryShop.setParentId(JSONUtil.parseObj(goodsCategoryJsonArray.get(i)).getStr("parentId"));
int sortSize = getSort(GOODS_CATEGORY_SHOP_JD_KEY);
goodsCategoryShop.setSort(sortSize);
addSize(GOODS_CATEGORY_SHOP_JD_KEY);
goodsCategoryShop.setShopId(jDConfigProperties.getShopId());
goodsCategoryShop.setTenantId(jDConfigProperties.getTenantId());
goodsCategoryShop.setEnable(CommonConstants.YES);
goodsCategoryShop.setCreateTime(LocalDateTime.now());
goodsCategoryShop.setDelFlag(DelFlagEnum.SHOW.getValue());
goodsCategoryShop.setDescription(ProductChannelEnum.JINGDONG.getDesc());
baseMapper.insert(goodsCategoryShop);
}
}
看到下面这一句,其实有给租户字段赋值的,那为啥还会null呢?
goodsCategoryShop.setTenantId(jDConfigProperties.getTenantId());
那就肯定是jDConfigProperties.getTenantId()有问题了
好吧,直接说结论,Nacos中,没有配置相应的租户字段呗,
加上租户字段后, 问题解决!
四、参考文章
【项目实战】商城中基于MybatisPlus多租户功能逻辑设计
【异常】因为忘加了租户查询条件,导致重复ID导入失败Duplicate entry ‘XXX‘ for key ‘PRIMARY‘
【异常】因多租户字段缺少导致Error updating database. Column ‘tenant_id‘ cannot be null