简体   繁体   中英

Is it good practice to initialize fields inside a JPA entity getter?

In POJO Java beans such code can be beneficial, especially with collections:

class POJO {
    private Collection<X> col;

    public Collection<X> getCol() {
        if (col == null)
           col = new SomeCollection<X>();

        return col;
    }
}

It makes possible for the code using POJO to call pojo.getCol().isEmpty() without an additional null check, thus making the code clearer.

Suppose the POJO class is a JPA entity, is it still safe to do that? By initializing the collection from null to an empty one the persistent data won't be changed, but still, we are modifying the object and thus the persistence provider may run some side effects upon flushing the persistence context. What do we risk? Portability maybe?

I do not see it as a good practice, more as some very rarely needed optimization. Maybe lazy initialization can make sense if SomeCollection is extremely heavy to create. Instead you can initialize it when declared (code is cleaner at least for my eyes):

class POJO {
    private Collection<X> col  = new SomeCollection<X>();

    public Collection<X> getCol() {
        return col;
    }
}

There is no side effects in flush or portability issues and you have one null check less.

I would strongly discourage lazy initialization for properties in an ORM entity.

We had a serious issue when doing lazy initialization of an entity property using Hibernate, so I would strongly discourage it. The problem we saw was manifest by a save taking place when we were issuing a search request. This is because when the object was loaded the property was null, but when the getter was called it would return the lazy initialized object so hibernate (rightly) considered the object dirty and would save it before issuing the search.

In general it is a good idea to use empty collections instead or null (for fields that are collections).

But I don't recommend the way you do in the getter.

In my personal opinion the "rule" above should also be used for the internal representation of the object too. So you go better with:

class POJO {
    private Collection<X> col  = new SomeCollection<X>();

Anyway if you want want to make it more save, you need to guard every way you update the col reference. But in a JPA application this should be a very raw use case.

Lazy initialization is very common and fine to do.

There are trade-offs versus initializing in the constructor or variable definition:

Pro

  • Lazy initialization is generally more efficient, it defers the cost of creating the value, which may never be required or replaced with some other value. This is very common in JPA, where existing object are read from the database, and their values are always replaced.
  • It allows for a null value to have meaning, this is more typical with Boolean values, where null means the default which is lazily assigned based on something else which is not know at creation time.
  • If the value is transient or nulled out some how, the lazy initialize can prevent null pointers.

Con

  • If the field is accessed directly you could still get a null-pointer.
  • Setting the default value in the variable definition is more clear.
  • If the object is used concurrently, lazy initialization can be a concurrency issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM