Spring Boot无Entity/Repository时JPA原生查询报错排查
问题排查结论
空指针异常的直接原因是EntityManager未完成依赖注入,同时代码中存在SQL拼接语法错误,两个问题均需修复。
- 空指针触发点:你在Controller中仅声明了
EntityManager em;属性,未添加任何依赖注入注解,Spring容器启动时不会为该属性赋值,属性值默认为null。执行em.createNativeQuery(sql)时本质是在null对象上调用方法,直接抛出空指针,和SQL写法无关。
修复方式:使用JPA规范的@PersistenceContext注解注入EntityManager,不要直接使用@Autowired注入(Spring对EntityManager做了线程安全代理,@PersistenceContext是标准注入方式):// 替换原有无注解的EntityManager声明 @PersistenceContext private EntityManager em; - 隐藏的SQL语法错误:就算EntityManager注入成功,你写的SQL拼接逻辑也会执行失败。当前拼接逻辑会生成带多余双引号的非法SQL,实际拼接出的字符串为
"SELECT * FROM"yourschema.yourtable,完全不符合SQL语法。
正确的SQL拼接写法如下,建议额外增加schema、表名白名单校验,避免直接拼接参数带来的SQL注入风险:// 错误写法:字符串内部多了双引号,且拼接逻辑写在字符串字面量里 // String sql = "\"SELECT * FROM\" + schemaName + \".\" + tableName "; // 正确写法 String sql = String.format("SELECT * FROM %s.%s", schemaName, tableName);
提示:你代码中判断
query == null的逻辑完全无效,只要EntityManager正常初始化,createNativeQuery方法不会返回null。之前的异常发生在调用createNativeQuery的瞬间,根本走不到后续的null判断逻辑。
修复后可正常运行的代码参考
import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class ConfigController implements ConfigApi { @PersistenceContext private EntityManager em; @GetMapping(value = "/config/test/{tableName}/{schemaName}") public List<Object[]> getList(@PathVariable("tableName") String tableName, @PathVariable("schemaName") String schemaName) { // 生产环境请在此处增加白名单校验,仅允许访问指定schema和表,防范SQL注入 String sql = String.format("SELECT * FROM %s.%s", schemaName, tableName); Query query = em.createNativeQuery(sql); return query.getResultList(); } }
内容的提问来源于stack exchange,提问作者Doncarlito87
相关产品推荐
相关产品推荐

