macrozheng/mall-swarm · error
创建产品出错
Error message
创建产品出错:{} What it means
relateAndInsertList uses reflection to reset each item's id, set productId, and call the DAO's insertList method while inserting child records (attributes, SKUs, etc.) for a product. Any reflection failure (NoSuchMethodException, IllegalAccessException), or any MyBatis/database failure while batch inserting, is caught and rethrown as a RuntimeException whose message is logged as '创建产品出错' (error creating product). Because it uses reflection, the original exception type and stack trace are lost, leaving only e.getMessage().
Solutions
- Log the full exception with a stack trace instead of only e.getMessage(), and rerun create/update to see the real root cause.
- Verify every object in the related list is the expected type with setId(Long), setProductId(Long), and that its DAO has insertList(List).
- Check the database constraints/schema for the relation table (columns, unique keys, nullable fields) against the data being inserted.
- Replace the reflection-based insertion with direct typed DAO calls so failures surface as compile-time and MyBatis errors.
- Break very large related lists into smaller batches for insertList.
Example fix
// before
catch (Exception e) {
LOGGER.warn("创建产品出错:{}", e.getMessage());
throw new RuntimeException(e.getMessage());
}
// after
catch (Exception e) {
LOGGER.error("创建产品出错", e);
throw new RuntimeException("插入产品关联数据失败: " + e.getMessage(), e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling create/update, validate related lists and required product id
if (CollectionUtils.isEmpty(product.getStepList())) { /* skip or fail fast */ }
for (Object item : allRelatedItems) {
try {
item.getClass().getMethod("setProductId", Long.class);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Related item missing setProductId: " + item.getClass());
}
} Type guard
boolean isRelatable(Object item) {
return item != null
&& hasMethod(item, "setId", Long.class)
&& hasMethod(item, "setProductId", Long.class);
}
private boolean hasMethod(Object o, String name, Class<?>... pts) {
try { o.getClass().getMethod(name, pts); return true; }
catch (NoSuchMethodException e) { return false; }
} Try / catch
try {
productComponentService.create(product);
} catch (RuntimeException e) {
LOGGER.error("产品创建失败(关联数据插入)", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new MallException("产品关联数据插入失败,请检查关联列表与数据库约束", e);
} Prevention
- Always log the full exception with stack trace, not just getMessage().
- Use typed DAO calls instead of reflection where possible to catch errors at compile time.
- Validate related DTO types and required fields before create/update.
- Run create/update inside a transaction so partial inserts roll back.
- Add integration tests covering each relation list (attribute, SKU, steps) against a real schema.
When it happens
Trigger: Calling PmsProductServiceImpl.create, update, or handleUpdateSkuStockList when a related list item lacks setId/setProductId methods (wrong DTO type), or when MyBatis insertList fails (SQL error, duplicate key, null column, list too large for the DB statement limits).
Common situations: Mapping the wrong entity class into a related list during create/update; DB schema drift so a column no longer exists; inserting a batch exceeding DB size limits; product relation records violating constraints (e.g., duplicate SKU barcodes).
Related errors
AI-assisted analysis of macrozheng/mall-swarm@04c442fe31 (2026-09-08).
Data as JSON: /api/errors/78fd16a160fb5b55.
Report an issue: GitHub.
Appendix: source
Thrown at mall-admin/src/main/java/com/macro/mall/service/impl/PmsProductServiceImpl.java:322
* 建立和插入关系表操作
*
* @param dao 可以操作的dao
* @param dataList 要插入的数据
* @param productId 建立关系的id
*/
private void relateAndInsertList(Object dao, List dataList, Long productId) {
try {
if (CollectionUtils.isEmpty(dataList)) return;
for (Object item : dataList) {
Method setId = item.getClass().getMethod("setId", Long.class);
setId.invoke(item, (Long) null);
Method setProductId = item.getClass().getMethod("setProductId", Long.class);
setProductId.invoke(item, productId);
}
Method insertList = dao.getClass().getMethod("insertList", List.class);
insertList.invoke(dao, dataList);
} catch (Exception e) {
LOGGER.warn("创建产品出错:{}", e.getMessage());
throw new RuntimeException(e.getMessage());
}
}
}
View on GitHub (pinned to 04c442fe31)