Search code examples
javajpaeclipselink

Avoid Instantiation of IndirectList in Eclipselink


I have a simple OneToMany Relation between a Parent and a Child.

Parent:

@OneToMany(mappedBy = "parent", orphanRemoval = true, cascade = CascadeType.ALL)
private List<Child> children = new ArrayList<>();

Child:

@ManyToOne(optional = false)
@JoinColumn(name = "PARENT_ID", nullable = false)
private Parent parent;

Because a parent can have a big amount of children I wanted to take advantage of Lazy Instantiation of Indirect Collections:

IndirectList and IndirectSet can be configured not to instantiate the list from the database when you add and remove from them. IndirectList defaults to this behavior. When Set to true, the collection associated with this TransparentIndirection will be setup so as not to instantiate for adds and removes. The weakness of this setting for an IndirectSet is that when the set is not instantiated, if a duplicate element is added, it will not be detected until commit time.

As the default FetchType of OneToMany is LAZY and I am using a List for my Collection, loading a parent from the database causes an IndirectList to be used for the relation. As soon as I add another child to that parent I can see that a select query for the children of that parent is executed.

How can I change that? I am using Eclipselink 2.6.4 (org.eclipse.persistence:eclipselink:2.6.4).

I also tried to use a DescriptorCustomizer to call org.eclipse.persistence.mappings.CollectionMapping.setUseLazyInstantiationForIndirectCollection(Boolean) on my relation, but this seemed to have absolutely no effect.

After debugging into the Method org.eclipse.persistence.indirection.IndirectList.add(E), I was able to see that the Method call to org.eclipse.persistence.indirection.IndirectList.shouldAvoidInstantiation() at line 206 returned false, because org.eclipse.persistence.indirection.IndirectList._persistence_getPropertyChangeListener() at line 1007 returns null and null is not instanceof AttributeChangeListener. Because of this the relation is then instantiated by org.eclipse.persistence.indirection.IndirectList.getDelegate() in line 216.

To me this seems like a bug, but I don't know enough about this implementation to be sure.


Solution

  • Change tracking is required to support not instantiating lazy collections when making modifications. Change tracking is enabled when using weaving as described here: https://www.eclipse.org/eclipselink/documentation/2.5/concepts/app_dev007.htm