Spring JPAとHibernateの両方のソースコードを掘り下げた後、私は自分の問題を解決することができました。私はこれがそれを解決する良い方法ではないと確信していますが、私が見つけることができる唯一のものです。
SingularAttributePath
クラスを拡張して、クエリの「注文」部分のラッパーを実装しました。このクラスには、実際のクエリに挿入される文字列を生成するrenderメソッドがあります。私の実装は次のようになります
@Override
public String render(RenderingContext renderingContext) {
String render = super.render(renderingContext);
render = "MYPACKAGE.NSORT(" + render + ")";
return render;
}
次は、SimpleJpaRepositoryクラスのOrder変換機能を拡張しました。デフォルトでは、これはQueryUtils.toOrders(sort, root, builder)
を呼び出して行います。しかし、それを呼び出すメソッドが不可能であったので、私はtoOrder
メソッドを自分自身と呼び、結果を自分の好みに変えました。
これは、結果のすべての注文をSingularAttributePath
クラスのカスタム実装に置き換えることを意味します。余分に私はPageable
クラスによって使用されるSort
クラスを拡張して、何がラップされ、何がないか(NaturalOrderと呼ばれる)を制御できるようにしました。しかし、私は1秒でそれに行きます。私の実装は
// Call the original method to convert the orders
List<Order> orders = QueryUtils.toOrders(sort, root, builder);
for (Order order : orders) {
// Fetch the original order object from the sort for comparing
SingularAttributePath orderExpression = (SingularAttributePath) order.getExpression();
Sort.Order originalOrder = sort.getOrderFor(orderExpression.getAttribute().getName());
// Check if the original order object is instantiated from my custom order class
// Also check if the the order should be natural
if (originalOrder instanceof NaturalSort.NaturalOrderm && ((NaturalSort.NaturalOrder) originalOrder).isNatural()){
// replace the order with the custom class
Order newOrder = new OrderImpl(new NaturalSingularAttributePathImpl(builder, expression.getJavaType(), expression.getPathSource(), expression.getAttribute()));
resultList.add(newOrder);
}else{
resultList.add(order);
}
}
return resultList;
(いくつかのチェックが省略されている)、この近くに見えるリターンリストは、query.orderBy(resultlist)
を呼び出すことで、クエリに追加されます。それはバックエンドのためのものです。
ラップ条件を制御するために、私はPageable
(これを数行前に戻します)で使用されているSort
クラスも拡張しました。私が追加したい唯一の機能は、Direction列挙型に4つのタイプがあることでした。
- ASC(デフォルトの昇順)
- DESC(デフォルト降順)
- NASC(通常昇順)
- NDESC(通常降順)
最後の二つの値のみがプレースホルダとして機能します。彼らは条件で使用されるisNatural
ブール値(拡張の変数Order
クラス)を設定します。それらがクエリに変換されるとき、それらはデフォルトのバリアントにマップされます。
public Direction getNativeDirection() {
if (this == NaturalDirection.NASC)
return Direction.ASC;
if (this == NaturalDirection.NDESC)
return Direction.DESC;
return Direction.fromString(String.valueOf(this));
}
は、最後に私がPageableHandlerMethodArgumentResolver
で使用されるSortHandlerMethodArgumentResolver
を置き換えます。これは、私のNaturalSort
クラスのインスタンスを作成し、デフォルトのSort
クラスの代わりにPageableオブジェクトに渡すことだけです。
最後に、同じRESTエンドポイントを呼び出すことができますが、結果はソート方法が異なります。
Default Sorting
/api/v1/items?page=0&size=20&sort=name,asc
Natural Sorting
/api/v1/items?page=0&size=20&sort=name,nasc
私は、このソリューションは、同一または自然のソートとスプリングJPAに関する派生問題を持っている人を助けることができると思います。ご質問や改善がありましたら、お知らせください。
名前はユーザーによって設定されているので、実際にはオプションではありません。だから私はその情報の内容に影響を与えません。 –
findAllメソッドから生成されたクエリにネイティブSQLを追加する方法はありますか? –
@RobinHermansしたがって、入力したテキストのフォーマットは事前に定義されていませんか?つまり、そのユーザーは_「これは第2グループです」_と入力することができます_これはソート順で_「これは第10のグループです」_の前に来なければなりませんか? –