在Spring Data JPA查询中添加COLLATE

3
我有一个简单的JPA Repository,其中包含派生查询和本地查询。现在,我需要(或者至少想要)为给定的查询指定排序规则,例如:
public interface UserRepository extends JpaRepository<User, Long> {

    @Query(value = "select * from users u order by u.firstname collate :language", nativeQuery = true)
    List<User> findAllUsersCollate(@Param("language") String language);

}

就我而言,派生查询不支持排序规则。
当我尝试使用参数指定排序规则名称时,问题就出现了。如果使用硬编码的排序规则,则没有问题。
@Query(value = "select * from users u order by u.firstname collate hun", nativeQuery = true)

工作正常,但不太合适。
注意:在示例中,“hun”是具有hu_HU区域设置的自定义排序名称。
我认为问题出在参数替换上。是否有一种方法可以使用Spring Data JPA Query Methods之一指定给定查询的排序方式?如果没有,如何创建一个接受排序参数并转换为有效SQL查询的查询?
1个回答

0

这是一个跟进帖子,最终我想到了一个可能的解决方案。

我使用了自定义的JPA存储库,详情请参考这里。例如,基本存储库是UserRepository,自定义存储库是UserRepositoryCustom,并由相应的实现类UserRepositoryCustomImpl来实现。查询语句的定义方式如下:

select * from users u order by u.firstname collate _COLLATION_

UserRepositoryCustomImpl除了实现UserRepositoryCustom接口外,还继承了一个AbstractCustomImpl类,该类中进行COLLATION占位符的替换。通过这种方式,其他需要排序规则的存储库也可以实现这个抽象类。

public abstract class AbstractCustomImpl {

    @PersistenceContext
    private EntityManager entityManager;

    @Value( "${...}" )
    private String defaultCollation;

    @Value( "${...}" )
    private String hungarianCollation;

    private static final String COLLATION_REGEX = "_COLLATION_";
    private static final String HUNGARIAN_LANGUAGE_CODE = "hu";

    public Query createCollatedQueryFromQueryString(String queryString, Locale locale, Class<?> resultClass){
        queryString = replaceTokensWithCollationString(queryString, locale);
        return entityManager.createNativeQuery(queryString, resultClass);
    }

    private String replaceTokensWithCollationString(String queryString, Locale locale){
        if(Objects.equals(locale.getLanguage().toLowerCase(), HUNGARIAN_LANGUAGE_CODE)){
            return queryString.replace(COLLATION_REGEX, hungarianCollation);
        } else {
            return queryString.replace(COLLATION_REGEX, defaultCollation);
        }
    }
}

然后,在UserRepositoryCustomImpl中,使用createCollatedQueryFromQueryString方法。
    @Override
    public List<User> findAllByOrderByLastnameAscFirstnameAsc(..., Locale locale) {
        Query query = createCollatedQueryFromQueryString(FIND_BY_QUERY, locale, *.class);
        return query.getResultList();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接