Spring Boot集成Oracle时@Query注解插入数据失效问题排查
问题:INSERT语句无法保存数据到Oracle数据库,怀疑@Query注解失效
我尝试执行INSERT语句,但数据无法保存到Oracle数据库,推测是@Query注解未正常工作,相关代码如下:
Controller代码
@Component //@RequestMapping("/api/v1") public class EmployeeControllerImpl implements EmployeeController{ @Autowired public EmployeeService employeeService; @Override @PostMapping("/addEmployee") public Employee addEmployee(@RequestBody Employee emp) { return employeeService.addEmployee(emp); } }
Service代码
@Component public class EmployeeServiceImpl implements EmployeeService{ @Autowired public EmployeeRepository employeeRepository; @Override public Employee addEmployee(Employee emp) { return employeeRepository.addEmployee(emp); } }
Repository接口代码
@Repository public interface EmployeeRepository extends JpaRepository<Employee, Integer > { @Query(value = "insert into employee (fname, lname, gender, age, contactNumber, empEmail, empPass) " + "VALUES (:fname, :lname, :gender, :age, :contactNumber, :empEmail, :empPass)", nativeQuery = true) Employee addEmployee(Employee emp ); }
Employee实体类代码
@Data @Entity @Table(name="Employee") @Getter @Setter public class Employee { @Id @Column(name = "employee_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private int empId; @Column private String fname; @Column private String lname; @Column private String gender; @Column private int age; @Column private String contactNumber; @Column private String empEmail; @Column private String empPass; }
application.properties配置
server.port:8082 spring.datasource.url=jdbc:oracle:thin:@localhost:1521/orcl spring.datasource.username=system spring.datasource.password=oracle spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver spring.jpa.database-platform=org.hibernate.dialect.OracleDialect spring.jpa.hibernate.ddl-auto=update spring.jpa.generate-ddl=true spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
问题原因及解决方案
核心问题分析
- @Query执行INSERT缺少必要注解:默认@Query仅支持查询操作,执行INSERT/UPDATE/DELETE这类修改操作时,必须添加
@Modifying和@Transactional注解,否则不会触发执行。 - 参数绑定错误:自定义SQL中使用
:fname这类参数,但方法参数是Employee对象,没有正确映射属性,导致参数无法传递到SQL中。 - 返回值错误:INSERT语句不会返回实体对象,定义返回值为Employee是错误的,应该用void或int(影响行数)。
- 冗余操作:Spring Data JPA的
JpaRepository已经自带save()方法,完全可以直接用来插入数据,无需自定义INSERT语句。
方案一:修复自定义addEmployee方法
修改Repository接口,补充必要注解并修正参数绑定:
@Repository public interface EmployeeRepository extends JpaRepository<Employee, Integer > { @Modifying @Transactional @Query(value = "insert into employee (fname, lname, gender, age, contactNumber, empEmail, empPass) " + "VALUES (:emp.fname, :emp.lname, :emp.gender, :emp.age, :emp.contactNumber, :emp.empEmail, :emp.empPass)", nativeQuery = true) void addEmployee(@Param("emp") Employee emp ); }
注意:如果需要返回影响行数,可将返回值改为int。
方案二:使用JpaRepository自带save方法(推荐)
直接删除自定义的addEmployee方法,利用JPA原生能力:
- 修改Repository接口:
@Repository public interface EmployeeRepository extends JpaRepository<Employee, Integer > { // 无需自定义方法,直接使用父类的save() }
- 修改Service实现:
@Component public class EmployeeServiceImpl implements EmployeeService{ @Autowired public EmployeeRepository employeeRepository; @Override public Employee addEmployee(Employee emp) { return employeeRepository.save(emp); } }
额外优化点
- Employee实体类中
@Data注解已经包含了@Getter和@Setter,可删除这两个冗余注解。 - Controller类建议替换
@Component为@RestController,更符合API控制器的语义(包含@Component和@ResponseBody)。 - 检查Oracle版本:如果是12c以下版本,
GenerationType.IDENTITY可能不支持,需要改用SEQUENCE生成主键:
@Id @Column(name = "employee_id") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "emp_seq") @SequenceGenerator(name = "emp_seq", sequenceName = "EMPLOYEE_SEQ", allocationSize = 1) private int empId;
内容的提问来源于stack exchange,提问作者Simran Mhaske
相关产品推荐
相关产品推荐

