You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot删除用户触发InvalidDataAccessApiUsageException问题排查

问题解决与优化方案

1. DELETE请求异常修复

你遇到的InvalidDataAccessApiUsageException: Unable to locate persister: java.lang.Integer异常,核心原因是**entityManager.remove()方法要求传入实体对象,而非主键ID值**。之前的deleteUser方法直接传了Integer类型的ID,导致JPA无法识别要操作的实体类。

修复代码示例

原错误实现:

public void deleteUser(Integer id) {
    entityManager.remove(id);
}

正确实现(先查询实体再删除):

@Transactional
public void deleteUser(Integer id) {
    User user = entityManager.find(User.class, id);
    if (user != null) {
        entityManager.remove(user);
    }
}

如果使用Spring Data JPA,更推荐直接继承JpaRepository,自带deleteById方法,无需手动实现:

public interface UserDao extends JpaRepository<User, Integer> {
    // 无需自定义deleteUser方法,直接用deleteById(Integer id)
}

2. 代码优化建议

  • 实体类规范:

    • 类名改为单数形式(Users → User),符合Java命名惯例
    • 关联映射补充完整:比如User与Expense的一对多关系,添加mappedBy属性避免双向关联的冗余表
    • 字段注解优化:用@Column明确字段名、非空约束等,比如@Column(nullable = false)
  • DAO层简化:

    • 放弃手动管理EntityManager,改用Spring Data JPA的Repository接口,减少重复代码,同时自带CRUD、分页等常用功能
  • 事务管理:

    • 在DAO或Service层的修改/删除方法上添加@Transactional注解,确保操作的原子性
  • Controller层优化:

    • 统一异常处理:用@RestControllerAdvice捕获JPA异常,返回友好的JSON错误信息
    • 参数校验:对请求参数添加@NotNull、@Min等注解,配合@Valid做入参校验

3. 关联保存费用(无需手动传user_id)

通过JPA的关联映射,实现自动关联用户与费用,无需手动在JSON中填写user_id:

步骤1:配置实体关联

User实体(一对多):

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    
    // 一对多关联Expense,mappedBy指定由Expense的user字段维护关联
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Expense> expenses = new ArrayList<>();
    
    // getter、setter
}

Expense实体(多对一):

@Entity
public class Expense {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private Double amount;
    private String description;
    
    // 多对一关联User,nullable=false确保费用必须属于某个用户
    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    
    // getter、setter
}

步骤2:Controller层实现关联保存

通过URL路径参数获取用户ID,查询到User实体后设置给Expense,再保存:

@RestController
@RequestMapping("/expenses")
public class ExpenseController {
    @Autowired
    private ExpenseDao expenseDao;
    @Autowired
    private UserDao userDao;
    
    @PostMapping("/user/{userId}")
    public Expense saveExpense(@PathVariable Integer userId, @RequestBody Expense expense) {
        User user = userDao.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        expense.setUser(user);
        return expenseDao.save(expense);
    }
}

此时前端只需发送费用的基本信息JSON(无需user_id),请求URL为POST /expenses/user/1即可完成关联保存。

内容的提问来源于stack exchange,提问作者Musab Shaikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:45:28