Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it mandatory to instantiate collection fields in JPA?

Tags:

hibernate

jpa

I was reading an article in which the author had implemented an Entity class like this:

@Entity
public class Product {

 @OneToMany
 private List<Part> parts; // note the missing "= new ArrayList<Part>();"

 public Product() {
 }

 // getters and setters

}

I always used to instantiate collection fields, in this case parts, either inline (private List<Part> parts = new ArrayList<Part>();) or inside the constructor because as far as I can remember not doing so would lead to all kinds of NPEs.

I thought that things have changed in JPA 2 and now the JPA runtime automatically instantiates the field using runtime bytecode enhancement or reflection, so I gave it another try, however I still can't get it to work without instantiating the parts field, otherwise aProduct.getParts().add(aPart) would throw an NPE.

So my question is that is it possible to make this work without instantiating the parts field in both of Java SE and Java EE environments using Hibernate as the provider? If so, how?

like image 956
Behrang Avatar asked Dec 16 '22 21:12

Behrang


2 Answers

My understanding is that the JPA provider can only instantiate the field properly within an entity loaded from the DB. However, if you create a new (as yet transient) entity, you must ensure yourself that all fields are valid. Note that Hibernate/JPA is not aware of a newly created transient entity, until you actually attach it to a persistence context. And if you think about it, it is logical (at least to me): if you relied on JPA/Hibernate to instantiate your objects properly, you would build up a strong and intrusive implementation dependency to it, which would make it very difficult to impossible to ever work without it again.

So leaving the collection property uninitialized may be fine for entities which are never created afresh, only loaded from the DB. For classes where you do create new instances too, the simplest way to resolve this would be to provide two constructors: a default for Hibernate/JPA, and a parametrized one for the creation "by hand". In case you don't have parameters to set, you could also create a static factory method to initialize all required fields with default values.

like image 161
Péter Török Avatar answered Jan 04 '23 23:01

Péter Török


If you load an Entity from the datastore then you do NOT need to "instantiate" the field since it will be loaded from the datastore (if it existed at persistence). If the collection was null at persist() then when retrieving it, it will likely also be null (since that is the point of making a persistence mechanism transparent)

like image 31
DataNucleus Avatar answered Jan 05 '23 00:01

DataNucleus