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

Spring Data JPA Repository无法删除H2内存数据库数据

问题:Spring Data JPA的deleteById/delete方法无法删除数据,deleteAll正常(无关联关系场景)

问题现象

  • 基于Spring Boot搭建简单项目,包含User实体、JpaRepository及Controller,使用H2内存数据库
  • 调用deleteById()或delete()方法后,目标数据仍留存,无报错信息
  • deleteAll()方法可正常删除所有数据
  • 实体类未配置任何一对一/一对多关联关系

根因分析

问题核心在于User实体的id字段类型:使用了基本类型long而非包装类型Long。

Spring Data JPA处理实体删除时,会通过id判断实体是否为已持久化状态:

  • 基本类型long的默认值为0,而数据库自增id通常从1开始,JPA会将id为0的实体判定为「未持久化的新对象」,因此不会执行删除操作
  • 包装类型Long的默认值为null,当从数据库查询出实体后,id会被赋值为数据库生成的非null值,JPA能正确识别这是已持久化的实体,从而触发删除逻辑

解决方法

将User实体中的id字段类型从long修改为Long即可解决问题。

修改前的User实体

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id; // 问题所在:基本类型long

    @Column(name = "username", unique = true, nullable = false, length = 25)
    private String username;

    @Column(name = "password", nullable = false, length = 255)
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    // 重载equals、toString、hashCode方法
}

修改后的User实体

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id; // 修改为包装类型Long

    @Column(name = "username", unique = true, nullable = false, length = 25)
    private String username;

    @Column(name = "password", nullable = false, length = 255)
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
    // 重载equals、toString、hashCode方法
}

相关配套代码

UserRepository

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface UserRepository extends JpaRepository<User, Long> {

    @Query(value = "SELECT * FROM users u WHERE u.username = :username", nativeQuery = true)
    User findByUserName(@Param("username") String username);
}

UserController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
@RequestMapping("user")
public class UserController {
    Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    UserRepository userRepository;

    @PostMapping("/new")
    public User routeCreateUser(@RequestBody User user) {
        User newUser = userRepository.save(new User(user.getUsername(), user.getPassword()));
        logger.info("NEW: "+newUser);
        return newUser;
    }

    @DeleteMapping("/forget")
    public User routeDeleteUser(@RequestBody User user) {
        User stored_user = getUser(user.getUsername(), user.getPassword());
        if (stored_user != null) {
            userRepository.delete(stored_user);
            // userRepository.deleteById(stored_user.getId()); // 修改后此方法也可正常使用
            logger.info("DELETE: "+ stored_user);
            return user;
        }
        return null;
    }

    // 补充getUser方法实现
    private User getUser(String username, String password) {
        User user = userRepository.findByUserName(username);
        return (user != null && user.getPassword().equals(password)) ? user : null;
    }
}

application.properties配置

spring.datasource.url=jdbc:h2:mem:db0
spring.datasource.username=test
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:42:55