hibernatePerformance tuning

Don't use EAGER fetch type

Hibernate can use two types of fetch when you are mapping the relationship between two entities: EAGER and LAZY.

In general, the EAGER fetch type is not a good idea, because it tells JPA to always fetch the data, even when this data is not necessary.

Per example, if you have a Person entity and the relationship with Address like this:

@Entity
public class Person {

  @OneToMany(mappedBy="address", fetch=FetchType.EAGER)
  private List<Address> addresses;

}

Any time that you query a Person, the list of Address of this Person will be returned too.

So, instead of mapping your entity with:

@ManyToMany(mappedBy="address", fetch=FetchType.EAGER)

Use:

@ManyToMany(mappedBy="address", fetch=FetchType.LAZY)

Another thing to pay attention is the relationships @OneToOne and @ManyToOne. Both of them are EAGER by default. So, if you are concerned about the performance of your application, you need to set the fetch for this type of relationship:

@ManyToOne(fetch=FetchType.LAZY)

And:

@OneToOne(fetch=FetchType.LAZY)

Use composition instead of inheritance

Hibernate has some strategies of inheritance. The JOINED inheritance type do a JOIN between the child entity and parent entity.

The problem with this approach is that Hibernate always bring the data of all involved tables in the inheritance.

Per example, if you have the entities Bicycle and MountainBike using the JOINED inheritance type:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Bicycle {

}

And:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class MountainBike extends Bicycle {

}

Any JPQL query that hit MountainBike will brings the Bicycle data, creating a SQL query like:

select mb.*, b.* from MountainBike mb JOIN Bicycle b ON b.id = mb.id WHERE ...

If you have another parent for Bicycle (like Transport, per example), this above query will brings the data from this parent too, doing an extra JOIN.

As you can see, this is a kind of EAGER mapping too. You don't have the choice to bring only the data of the MountainBike table using this inheritance strategy.

The best for performance is use composition instead of inheritance.

To accomplish this, you can mapping the MountainBike entity to have a field bicycle:

@Entity
public class MountainBike {

    @OneToOne(fetchType = FetchType.LAZY)
    private Bicycle bicycle;

}

And Bicycle:

@Entity
public class Bicycle {

}

Every query now will bring only the MountainBike data by default.