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

  1. Log the full exception with a stack trace instead of only e.getMessage(), and rerun create/update to see the real root cause.
  2. Verify every object in the related list is the expected type with setId(Long), setProductId(Long), and that its DAO has insertList(List).
  3. Check the database constraints/schema for the relation table (columns, unique keys, nullable fields) against the data being inserted.
  4. Replace the reflection-based insertion with direct typed DAO calls so failures surface as compile-time and MyBatis errors.
  5. 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

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)