Spring Data JPA查询SpelEvaluationException:principal属性找不到
问题分析与解决办法
问题原因
你遇到的SpelEvaluationException核心原因是:Spring Data JPA解析@Query中的SPEL表达式时,默认根对象是方法的参数数组(java.lang.Object[]),而你直接引用的principal并不在这个参数数组里——principal属于Spring Security的SecurityContext上下文对象,无法从默认的SPEL根对象中获取,因此抛出“找不到属性或字段”的错误。
另外你的Repository方法返回值使用了原始类型List,属于类型不安全的写法,建议同步修正。
解决办法
提供两种可行方案,按需选择:
方案1:直接在SPEL中获取SecurityContext的principal
修改@Query中的SPEL表达式,通过SecurityContextHolder直接获取当前认证用户信息,绕过默认参数数组根对象的限制:
import org.springframework.security.core.context.SecurityContextHolder; @Query("select organization from Organization organization where organization.salesPerson.login = ?#{T(org.springframework.security.core.context.SecurityContextHolder).getContext().getAuthentication()?.principal?.username}") List<Organization> findBySalesPersonIsCurrentUser();
注:添加
?.空安全操作符可避免未认证时的空指针异常;将返回值改为List<Organization>,消除原始类型警告。
方案2:通过@AuthenticationPrincipal注入当前用户参数(可读性更强)
利用Spring Security的@AuthenticationPrincipal注解,直接将当前认证用户信息作为方法参数传入,再在@Query中引用该参数,这种方式更符合Spring设计习惯:
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.userdetails.UserDetails; @Query("select organization from Organization organization where organization.salesPerson.login = :#{#user.username}") List<Organization> findBySalesPersonIsCurrentUser(@AuthenticationPrincipal UserDetails user);
如果你的UserDetails实现类直接存储了用户名,还可以简化为直接注入用户名:
@Query("select organization from Organization organization where organization.salesPerson.login = ?1") List<Organization> findBySalesPersonIsCurrentUser(@AuthenticationPrincipal String username);
内容的提问来源于stack exchange,提问作者Muvvala Krupanandam
相关产品推荐
相关产品推荐

