0

I have entity that has several fields:

public class Some {
 private Foo foo;
 private Bar bar;
}

I want to have code which is capable to sort by foo and sort by bar depending on the request. I know that there is tool that could be used like this:

Sort sort = Sort.by(Sort.Direction.DESC, "foo");
Pageable pageable = PageRequest.of(page, limit, sort);

But it seems like this approach is not perfect because field names are hardcoded and in the case that some field name is changed and developer forgot to update this sorting code everything will look okay during compilation / startup stage, but will fail during runtime.

Is that possible to have alternative solution without hardcoding and duplicating same method several times just to change jpql query ?

6
  • 3
    No. You could use the JPA metadata (if generated) to get the names (which would lead to a compiler error) or write more extensive tests. But the Sort can also be constructed in your controller from the request (so the user selects them itself). Commented Sep 20, 2021 at 8:56
  • Side comment : not hard-coding field names, usually means having them passed by the caller and sent down to the datastore. This is usually a security nightmare (SQL injection, ...). Hard coding field names, IMHO, "is a feature, not a bug". At the very least, you should consider the security implications of not "somehow" hard coding them. (Yes, JPA helps, because it is normally not possible to have SQL injection by using the Criteria APIs as opposed to native / JPQL, but you always have to at least think about security). Commented Sep 20, 2021 at 9:03
  • @M.Deinum Passing parameters from controller will not help with code support/changes i think. Commented Sep 20, 2021 at 12:37
  • @GPI I didn't mean to pass this parameters from somewhere to DS. I thought maybe there is some feature that is based on reflection/annotation using and this feature would validate field name changes. Commented Sep 20, 2021 at 12:40
  • 1
    As I mentioned you can use the JPA metadata for this. You would need to modify your build to generate it and use that instead of the strings as names. That way, if you delete or rename a field compilation will fail. (until you start using it from ui with Sttringly typed fields again). Commented Sep 20, 2021 at 13:48

1 Answer 1

2

If you don't want to use a String for the names, you can use the JPA Metamodel. This metamodel you can also use the create queries with the criteria API.

Here is a nice blog post which explains how to generate and use the JPA Criteria Metamodel. But in short it comes down to adding a Maven plugin (or Gradle if you use that) to your compiler. During compilation it will now generate the metamodel.

With your sample class(es)

public class Some {
 private Foo foo;
 private Bar bar;
}

It will generate a Some_ class which you can then use to get the name of the properties. Some_.FOO will link to the foo attribute. Now if you rename foo to bar, compilation will fail as Some_FOO isn't available anymore.

Sign up to request clarification or add additional context in comments.

1 Comment

That is what I was looking for. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.