Spring Boot JPA+Postgres执行select报InvalidDataAccessResourceUsageException
问题根因
该异常是JDBC层返回了关系不存在/语法类错误,被Spring统一包装为InvalidDataAccessResourceUsageException,核心原因是应用中usr用户的数据库连接上下文,和pgAdmin里登录usr用户时的连接上下文配置不一致,90%以上的同类问题由以下两种场景触发:
- 场景1:表
X不在public默认schema下,仅给usr授予了表X的SELECT权限,未授予对应schema的USAGE权限,同时usr用户的默认search_path未包含表X所在schema。pgAdmin建立连接后会自动执行初始化语句调整search_path,因此手动执行查询正常;但应用连接池建立连接时使用数据库层面的用户默认配置,找不到目标表,PostgreSQL返回relation "X" does not exist错误,被PostgreSQL JDBC驱动归类为语法错误,最终被Hibernate转换为SQLGrammarException。 - 场景2:表
X开启了行级安全(RLS)策略,策略依赖会话级上下文变量(比如租户ID、当前用户标识)做权限校验。在pgAdmin中执行查询前手动设置过对应变量,因此查询正常;但应用连接池创建连接时未初始化这些变量,RLS策略执行时因缺少必要参数抛出错误。
排查步骤
- 跳过pgAdmin,使用和应用完全相同的连接参数,通过psql命令行工具登录usr用户,直接执行目标SELECT语句,确认是否报错。如果psql中直接提示关系不存在,可直接判定为schema权限/搜索路径问题。
- 若psql执行无报错,在应用数据源配置中添加连接初始化日志,打印连接建立后的search_path配置:
SHOW search_path;,和pgAdmin中usr用户执行同一句的返回结果做比对,确认配置差异。 - 执行以下SQL检查表
X是否开启行级安全:
SELECT relrowsecurity FROM pg_class WHERE relname = 'X';
返回值为t即代表表开启了RLS策略。
解决方案
针对schema权限与搜索路径问题
- 用超级用户登录数据库,给usr授予表
X所在schema的USAGE权限:
GRANT USAGE ON SCHEMA "替换为表X所在的schema名" TO usr;
- 给usr用户配置永久默认搜索路径,将表
X所在schema加入路径列表:
ALTER ROLE usr SET search_path TO "替换为表X所在的schema名", public;
- 重启应用清空连接池存量连接,重新执行查询验证即可。
注意:PostgreSQL权限模型和MySQL有区别,用户必须同时持有schema的USAGE权限和schema内对象的对应操作权限,才能正常访问对象,仅给表授权无法正常访问非public schema下的表。
针对RLS策略问题
- 执行以下SQL查看表
X上绑定的RLS策略定义,确认策略依赖的会话变量名:
SELECT polname, polqual FROM pg_policy WHERE polrelid = 'X'::regclass;
- 在应用数据源配置中添加连接初始化SQL,每次连接从连接池借出/创建时,自动设置策略依赖的会话变量,例如:
SET app.current_tenant_id = '替换为应用对应的租户ID值';
- 重启应用验证即可。
内容的提问来源于stack exchange,提问作者Hey StackExchange
相关产品推荐
相关产品推荐

