Sat. Apr 20th, 2024

Continuing my Java Tips from experience that I have learned from code reviews to different programming tasks.

Tip 16: Perform Bulk operations with Native Queries, or Stored Procedure

It can be very tempting to do an update like the following:

List<Person> people = ListUtils.safe(personRepository.findAll()).stream().filter person -> person.getAge() >= 60 ).map(person -> {
    person.setSeniorStatus(true);
    return person;
}).collect(Collectors.toList());

personRepository.saveAll(people);

However, doing this is more efficient than saving them one at a time. However, it would be even more efficient to do something like:

@Modifying
@Query("update Person p set p.seniorStatus = 1 where p.age >= 60")
void updateSeniorStatus();

Let the database perform the update across the tables. The Database can perform this update easier and faster than performing it in Java code.

Tip 17: Use try-with-resources

While this is not a performance-enhancing action, it is a resource-handling enhancement. Any object in Java that implements the AutoClosable interface can be used with the try-with resources. This guarantees any object created in the try, is properly closed when you exit the block. The prevents resource leading. An example would be:

static String readFirstLineFromFile(String path) throws IOException {
    try (FileReader reader = new FileReader(path);
         BufferedReader br =
                   new BufferedReader(reader)) {
        return br.readLine();
    }
}

This is extremely simple to illustrate that you can do multiple instantiations in the try field. When this code exits they will be closed properly without you having to do so. This could be extended with catch() and finally() blocks as well.

Tip 18: Text Block instead of String concatentation

We’ve all had those big blocks of text in our code that we have to insert for some reason. Often we have done the following:

String block = "Lorem ipsum dolor sit amet, has id vide aliquid nominati, nulla inciderint his et. His nisl maluisset efficiendi in. Qui erant verear ei, nec ex ullum tantas epicurei. Has ne aperiam deserunt. Vis ne delenit repudiare, nec gubergren sadipscing ne. Purto placerat cu est, no ferri solum sit.";

As one big long line that is difficult to read, because you have to keep scrolling to the right, or

String block = "Lorem ipsum dolor sit amet, has id vide aliquid nominati,"
    + " nulla inciderint his et. His nisl maluisset efficiendi in. Qui erant"
    + " verear ei, nec ex ullum tantas epicurei. Has ne aperiam deserunt. Vis ne"
    + " delenit repudiare, nec gubergren sadipscing ne. Purto placerat"
    + " cu est, no ferri solum sit.";

This generates no less than 9 String objects to create that String. Well now we have a text block, this could be changed to the following:

String block = """
Lorem ipsum dolor sit amet, has id vide aliquid nominati, \
nulla inciderint his et. His nisl maluisset efficiendi in. \
Qui erant verear ei, nec ex ullum tantas epicurei. Has \
ne aperiam deserunt. Vis ne delenit repudiare, nec gubergren \
sadipscing ne. Purto placerat cu est, no ferri solum sit. \

Ius ne quas choro, duo ad falli perpetua reformidans. Ne ius \
petentium philosophia. Id usu gloriatur contentiones, et elit \
minim duo, cetero noluisse partiendo usu id. Pro ei velit \
nostrud, pri choro dictas dissentiet ex.\
""";

That generates a single String object, if you do not want the new line characters where it appears in the block, inserting a “\” . The line above will get you 3 lines, with the 1st and 3rd being the text, and the 2nd a blank line.

Tip 19: Cache if you maintain a large number of in-memory object

Sometimes you need to maintain a large in-memory set/list/map of objects, when that happens you need to look at making use of a Cache. When you only need to keep a single instance of an object around, not every instance that is generated, then a cache maybe right for you.

Tip 20: Entity field dateCreated and lastUpdated

Many may not think they need it, but it is a set of data that you can not generate if you don’t collect it to begin with. When creating a database table, always add “date_created” and “last_updated” columns that are timestamps. This helps track changes in the data. Now in your Java code, when you create your entity class add this little tidbit:

    @PrePersist
    protected void onCreate() {
        this.dateCreated = ZonedDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        this.lastUpdated = ZonedDateTime.now();
    }

@PrePersist will set the timestamp for dateCreated when the item is first saved to the database. While @PreUpdate will update the timestamp for lastUpdated every time the item is updated. Make this a class that you derive all of your entities from and you a self-updating columns.

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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.