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
相关产品推荐
相关产品推荐

