Java Spring JPA调用MySQL存储过程报SQL Error 1064错误解决方案求助
问题根源
你写的存储过程调用SQL语法错误,MySQL存储过程的标准调用格式是CALL 存储过程名(参数1, 参数2, ...),你在@Query注解中错误的将两个参数用括号分别包裹,生成的实际执行SQL为CALL FindAllAccountsNames (36), ('customer'),MySQL解析到第一个参数括号结束时就判定存储过程调用已经结束,后续的, ('customer')属于非法语法,和你收到的报错提示完全匹配。
修复方案
1. 修正Repository层代码
直接修改@Query注解中的调用语句,将两个参数放到同一对括号内即可:
@Repository public interface AccountRepository extends JpaRepository<Account, Integer> { @Query(value = "CALL FindAllAccountsNames(:uid, :accType)", nativeQuery = true) List<String> findAllAccountsNames(@Param("uid") int uid, @Param("accType") String accType); }
2. 补充存储过程安全校验(推荐)
你当前存储过程中直接将传入的accType作为表名拼接动态SQL,如果该参数由用户端传入会存在严重的SQL注入风险,建议增加合法表名校验:
DELIMITER $$ CREATE PROCEDURE `FindAllAccountsNames` (in `uid` int, in `accType` varchar(16)) BEGIN -- 仅允许指定的表名被查询,根据你的业务实际支持的账户类型调整IN内的值 IF accType NOT IN ('customer', 'supplier', 'asset', 'liability', 'equity', 'income', 'expense') THEN SELECT -1; ELSEIF NOT EXISTS (SELECT `user`.`id` FROM `user` WHERE `user`.`id` = `uid`) THEN SELECT -1; ELSE SET @accNames = CONCAT('SELECT `name` FROM ', accType); PREPARE stmt FROM @accNames; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END$$ DELIMITER ;
效果验证
修改完成后重新调用接口,即可正常返回对应账户类型的名称列表,和你在MySQL Workbench中本地测试的结果一致。
内容的提问来源于stack exchange,提问作者Anser Waseem
相关产品推荐
相关产品推荐

