Spring 存储库查询中的表达式语言 (SpEL) 访问区域设置

Spring Expression Language (SpEL) access locale in Repository Query

我需要使用 SpEL 访问 Spring 存储库中的当前语言环境。

我有下一个Repository:

@Repository
public interface RoomRepository extends JpaRepository<Room, Long> {

    @Query(..."left join rc.roomClassTranslations rct on rct.language = ?#{SpEL expression})
    List<RoomDTO> findAllRooms(Sort sort);
}

我尝试了几个表达式,但 none 个有效。

#{@localeResolver.resolveLocale(#httpServletRequest).toLanguageTag()} "...) 这个表达式中的httpServletRequest 是null,如果我把它改成@httpServletRequest,就会报找不到bean 的错误。我也试过这样改写

#{LocaleContextHolder.getLocale().toLanguageTag()} 这将给出下一个错误:

EL1011E: Method call: Attempted to call method getLocale() on null context object.

那么如何在 SpEL 表达式中访问当前语言环境?

Spring 支持在使用 @Query.

定义的手动定义的查询中使用 restricted SpEL template expressions

Spring 数据公开了一个扩展点 EvaluationContextExtension

Spring Data JPA 将拾取所有 EvaluationContextExtension 类型的 beans 并使用它们来准备 EvaluationContext 以用于评估 SpEL 表达式@Query.

让我们以语言环境扩展为例。
@Component
public class LocaleEvaluationContextExtension
        implements EvaluationContextExtension {

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> properties = new HashMap<>(
                EvaluationContextExtension.super.getProperties());
        return properties;
    }

    @Override
    public String getExtensionId() {
        return "locale";
    }

    @Override
    public Object getRootObject() {
        return LocaleContextHolder.getLocale();
    }
}
查询方法定义应该是:
@Query(..."left join rc.roomClassTranslations rct on " +
        "rct.language = ?#{locale.language})
List<RoomDTO> findAllRooms(Sort sort);