2016. március 29., kedd


Lazy init vs initialization by definition for collection typed properties of JPA entities


How to initialize a collection typed property of a JPA entity? In order to make the Unit testing easier and the client code cleaner it is advisable to get an empty collection from the entity. Even if the entity has not been initialized by the JPA (based on database state), or in case of a newly instantiated entity. If null can be returned by the getter, the client code needs to be handle the situation.

In Unit tests, especially by using mocked objects, it can be extremely ugly to let the client code to check for possible null values.

We have two possibilities:

  1. Initialize by declaration
    JPA itself doesn't care whether the collection is initialized or not. When retrieving an Order from the database with JPA, JPA will always return an Order with a non-null list of OrderLines.

    It does so, because a relation can have 0, 1 or N elements, and that is best modeled with an empty, one-sized or N-sized collection. So it's best to make that an invariant by always having a non-null collection, even for newly created instances of the entity. That makes the production code creating new orders safer and cleaner. That also makes your unit tests, using Order instances not coming from the database, safer and cleaner.
    It is also possible to use Guava's immutable collections, e.g.,
    import com.google.common.collect.ImmutableList;
    // ...
    @OneToMany(mappedBy="order")
    List<Order> orders = ImmutableList.of();
    In this way, we are never creating a new empty list, but reusing the empty list of the framework. Therefore the performance argument is no longer relevant.

    In case of the setter can be accessed by the client, it might be a chance, to set the collection to null. In this case, a NullPointerException might occur. Therefore it is a good practice to avoid setting a collection to null in the setter.
  2. Lazy initialization in getter method
    There can be problems with lazy init using with hibernate, related to the search for entities. The JPA specification defines Flushmode to determine if the entities need to be written to the database (see https://en.wikibooks.org/wiki/Java_Persistence/Querying#Flush_Mode for details). In case of lazy init, Hibernate thinks the entity dirty, in case it has been loaded with null collection, but the getter returns an empty collection. If Flush Mode is set to AUTO, Hibernate writes the entity into the database before the search, which might cause performance problems.   

  

Nincsenek megjegyzések:

Megjegyzés küldése