Tip 21: Use Prepared Statements

When working with JPA/Hibernate make use of Prepared Statements that can be reused. Basically, I’m saying do not do the following:

Query query = JPA.em().createNativeQuery("select count(*) from user u inner join" +
    "address a where a.user_id=u.id and a.city='" + city + "'");

BigInteger val = (BigInteger)query.getSingleResult();

This is considered a statement and will have to be generated every time by Hibernate. Instead, do this using a prepared statement that can be reused:

Query query = JPA.em().createNativeQuery("select count(*) from user u inner join" +
    "address a where a.user_id=u.id and a.city=:city");
query.setParameter("city", city);

BigInteger val = (BigInteger)query.getSingleResult();

Or if you’re doing JPQL in your Repository interfaces, you could do it this way:

@Query(value = "select count(*) from user u inner join " +
    "address a where a.user_id=u.id and a.city=:city", nativeQuery = true)
BigInteger findAllByNameAndDate(@Param("city") String city);

Either of these 2 methods will create a prepared statement that can be reused multiple times, instead of a new one being created each time. It’s a minor change but a significant one.

Tip 22: Recursion

Recursion can be a saving grace in simplifying code, it can also be a curse. You must understand your stopping point in the recursion and how deep it may need to go. It is very possible and very likely you can and will blow the stack by too many recursive calls going deep. This can be costly in a high-performance system even if it doesn’t blow the stack. You need to judge how much recursion is too much. A few iterations deep v’s hundreds or thousands of interactions can significantly slow down your process.

Tip 23: Native Types

Java objects are created on the heap, while native types are created on the stack and are much smaller. Making use of native types are:

  • byte
  • short
  • int
  • long
  • float
  • double
  • char
  • boolean

If your data can be represented as one of these types and is short-lived, and you will not need to make use of methods of the native wrappers, this can significantly reduce memory usage, allocation time, and garbage collection. Make intelligent use of these. Remember these can not be NULL.

Tip 24: StringBuilder

I spoke in Tip 3: Parallel Stream thread-safety about the use of StringBuilder not being thread-safe. If thread safety isn’t a concern, then StringBuilder is far more efficient performance-wise for concatenating strings together, than StringBuffer, or String concatenation using the + method. StringBuilder is recommended when you need to concatenate a list of strings, 2 or 3 strings just use the + method.

Tip 25: StringUtils.replace() v’s String.replace()

If your doing a large number of Stirng.replace() consider switching it out with Apache Commons Lang StringUtils.replace(). This outperforms String.replace() as outlined Benchmarking JDK String.replace() vs Apache Commons StringUtils.replace(). It’s easy to make use of by including in your Maven Project:


The code change is simple enough to make from:

String test = "My test to show you.";

test.replace(“test”, “simple test”);

to this:

StringUtils.replace(test, “test”, “simple test”);

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.