如何使用Spring Boot自定义QUERY将User对象正确保存到数据库
问题原因分析
你的代码存在以下几处核心问题,导致写入操作报错但查询无异常:
- 表名使用了多数数据库的保留关键字
User,写入操作时会直接触发语法错误,查询未报错通常是因为查询场景未触发关键字校验逻辑 - 自定义写入方法缺少
@Modifying注解:Spring Data JPA 中@Query默认仅处理查询操作,执行INSERT/UPDATE/DELETE类修改操作必须加@Modifying声明为修改操作 - 参数绑定错误:方法传入参数是User对象,SpEL表达式需要指定参数名才能引用对应属性,原写法
#{userName}无法匹配到对应参数 - SQL语法错误:INSERT语句的正确关键字是
VALUES,原代码写的VALUE会触发SQL语法错误 - 自定义save方法的泛型声明和返回值不符合Spring Data JPA自定义修改方法的规范,修改类方法返回值应为影响行数(int/Integer)或void
正确实现方案
方案1:使用JpaRepository自带save方法(推荐,无需自行编写SQL)
绝大多数场景下直接使用Spring Data JPA封装好的通用save方法即可,不需要自己写原生SQL:
- 先修改表名避开保留关键字,避免后续语法冲突
@Entity @Table(name = "sys_user") // 修改为非关键字的表名 public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; private String userName; private String password; private boolean active; // 原有getter/setter保持不变 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } }
- Repository接口直接继承JpaRepository即可,不需要自定义save方法
// 第一个泛型为实体类类型,第二个为实体类主键类型 public interface UserRepository extends JpaRepository<User, Integer> { // 无需编写自定义save逻辑,JpaRepository已经自带了支持新增/更新的通用save实现 }
- 业务层直接调用自带方法即可
@Autowired private UserRepository userRepository; public void addUser(User user) { // 自带save方法会自动判断操作类型:主键为空执行新增,主键有值执行更新 userRepository.save(user); }
方案2:自定义原生INSERT实现忽略写入逻辑
如果业务确实需要用到INSERT IGNORE的去重写入逻辑,可以按以下规范修改代码:
public interface UserRepository extends JpaRepository<User, Integer> { // 修改操作必须加@Modifying注解,同时需要事务支持,事务注解也可以加在业务层调用方法上 @Modifying @Transactional @Query(value = "INSERT IGNORE INTO sys_user (user_name, active, password) " + "VALUES (:#{#user.userName}, :#{#user.active}, :#{#user.password})", nativeQuery = true) int saveIgnore(User user); }
注意事项:
- 数据库字段如果是JPA自动生成的,默认会把驼峰属性转为下划线命名,比如
userName对应数据库字段user_name,如果你的数据库字段本身是驼峰命名,自行修改SQL里的字段名即可 - 参数引用统一使用
:#{#参数名.属性名}的格式,此处方法参数名是user,所以写:#{#user.userName} - 若坚持要使用
User作为表名,需要加转义符处理,比如MySQL中可以写成@Table(name = "User"),但非常不推荐,后续维护容易出现未知问题
内容的提问来源于stack exchange,提问作者Am Ventures
相关产品推荐
相关产品推荐

