Schlagwort: Java

How to use JPA (and DBs) correctly

Today was a day of greater insights at work. We (Java guys and our DBA) have been discussing how to optimize database access from our Java application. Of course we use JPA (by OpenJPA).

We came to the conclusion, that we all are great fans of interfaces and separation of concerns, but we failed to apply it when we designed our persistence layer.

In our application, the jpa entities are exact copies of the tables in the database. Currently we do a refactoring of our database design, and this hits the application code hard.

The following steps to enlightenment we climbed today:

  1. When you access the db by scenario/use case dependent views, you decouple the db design from the java entity design and vice versa. Whenever you change your db design, this goes with 0 effort for the java team.
  2. JPA is capable of integrating values from several tables in one entity, thus JPA entities work like RW-views. Whenever the db design changes, you (should) only have to adjust the JPA annotations to get it working again.
  3. Use good old component architecture for your Java/Application layer. Each component owns its own private JPA entities and some specific public transfer objects to send and receive information to and from a component.
  4. Your private JPA entities hold only necessary information. This holds especially true for relations between entities. If you don’t need a relation in your component, just load it as an ID field instead. This will automatically cut unnecessary eager fetches.

If you have considered this points, also read this article on optimizing the use of JPA by

  • eager fetching if you need all members of a collection instead of N+1 selects (you can do this with JQL fetch queries, too!)
  • lazy loading if you don’t need related objects.
  • JPA pagination instead of java pagination for big result sets.
  • load specific columns if you don’t need the whole object.

Why to only use immutable variables for Java hashCode()

There are lots of websites which explain to Java coders, that whenever you override equals() you also have to override hashCode(). You need to override those methods especially when you use JPA. Eclipse is a nice tool, that helps you with generating those „custom implementations“.

But beware of the such generated hashCode() methods. It will ruine your day when you use HashSet or HashTable containers and expect them to work like they did with the standard implementation.

The rule of thumb is:

„Only include those variables in the hashCode generation, which will not change during the usage time of the object.“

Why? Just think about a simple class „Foo“ that has a mutable (means normal) property named „value“ and a Eclipse generated hashCode() method implementation (which will use the field value to calculate the hash). Given this class, what will this little test print out?:

    public static void main(String[] args) {
    
        Foo f = new Foo();
        
        f.value = 100;
        
        HashSet<Foo> set = new HashSet<Foo>();
        
        set.add(f);
        
        f.value = 101;
        
        if (set.contains(f)){
            System.out.println("All fine!");
        } else {
            System.err.println("WTF!?");
        }
        
    }

The right answer is: „WTF!?“

Believe it or not, the HashSet will not recognise the instance f anymore, because HashSet and HashTable will use the hashCode() method before the equals() method will be used to identify if an object is included in the container.

So only use immutable variables like ids that will not change during the usage of the class. Such a hashCode() method will still comply to the contract that

Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.