Java 报错:Cannot invoke setCreatedAt (Long) on the primitive type void 排查与修复

7次阅读
没有评论

前言

开发中写链式调用的时候,经常会碰到这个编译报错:Cannot invoke setCreatedAt(Long) on the primitive type void。第一眼容易懵,其实根源非常简单,本文把原因、错误示例、正确写法、避坑方案一次性整理清楚,MyBatis-Plus 项目高频遇到。

报错核心原因

你在一个返回值为 void(或者 int) 的方法返回结果上,继续链式调用 .setCreatedAt()。 void 不是对象,没有实例,不支持 . 调用任何成员方法,编译器直接报错。

最常见场景:保存 / 插入方法 save() / insert() 执行之后,想链式给实体设置字段。 save()、mapper.insert() 这类方法返回 void /int(影响行数),不是实体对象,不能继续链式 set。

❌ 错误示例

场景 1:MyBatis-Plus Mapper insert 后链式 set

// 错误代码
userMapper.insert(user)
        .setCreatedAt(System.currentTimeMillis());

insert 返回 int(数据库受影响行数),不是 User 对象,后面不能跟 .setCreatedAt()。

场景 2:自定义 Service 方法返回 void

// 方法定义
public void saveUser(User user) {
    userMapper.insert(user);
}

// 调用处,直接报错
saveUser(user).setCreatedAt(System.currentTimeMillis());

场景 3:链式顺序颠倒(高频踩坑)

先执行保存,再去设置实体属性,顺序完全反了。

// 错误
user.setCreatedAt(1L).insert();

✅ 正确写法

方式 1:普通写法,先 set 再保存

User user = new User();
user.setCreatedAt(System.currentTimeMillis());
user.setUserName("test");
userMapper.insert(user);

方式 2:Lombok 链式实体(推荐)

实体类加上注解 @Accessors(chain = true),支持 setter 链式返回自身:

@Data
@Accessors(chain = true)
public class User {
    private Long id;
    private String userName;
    private Long createdAt;
}

业务代码:

User user = new User()
        .setCreatedAt(System.currentTimeMillis())
        .setUserName("test");
userMapper.insert(user);

🚀 进阶方案:自动填充时间(推荐生产使用)

每次手动 setCreatedAt 很繁琐,MyBatis-Plus 自带自动填充,不用业务代码手动赋值。

  1. 实体字段加注解
@TableField(fill = FieldFill.INSERT)
private Long createdAt;
  1. 实现 MetaObjectHandler 填充处理器
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createdAt", System::currentTimeMillis, Long.class);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时间填充,按需开启
        this.strictUpdateFill(metaObject, "updatedAt", System::currentTimeMillis, Long.class);
    }
}

配置完成后,新增数据自动填充 createdAt,业务代码完全不用写 setCreatedAt。

✅ 快速自查清单

  1. 定位报错行:看 .setCreatedAt() 前面的方法,确认返回值是不是 void / int
  2. 调整执行顺序:先给实体 set 字段,再执行 insert /save/update
  3. 想要链式:实体开启 @Accessors(chain = true),保存方法放在链式最后一行
  4. 时间字段优先使用 MyBatis-Plus 自动填充,减少样板代码

小结

这个报错本质不是框架 bug,是链式调用顺序理解错误:setter 是实体对象的方法,保存方法是执行数据库操作,二者不能在保存之后继续链式。只要记住:先组装实体,再入库,基本就能避开这个坑。

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码