How can I change the fetch type of a field on a BLC core class?
On ManyToOne
relationships the default fetch type is set to Eager. While normally this is what is wanted, it will cause Hibernate to issue joins to fetch these entities. There are times when we do not want this and if it is a field on an extended class, or a custom class, we can simply set it to fetch = FetchType.LAZY
and we're all set. But in the case of fields that are coming from the BLC project they are not as easy to reach.
Fortunately there is a way around this by leveraging load time weaving. In this particular case, we will take FulfillmentGroup
's Address
and Phone
and switch them to FetchType.Lazy
to prevent the joins on these tables.
Create an interface for the class that will have the getter/setters:
public interface LazyFulfillmentGroup { public Address getAddress(); public void setAddress(Address address); public Phone getPhone(); public void setPhone(Phone phone); }
Create an @Embeddable
implementation class that will use the @Parent
to the class that will be woven into. In this class, you will create any/all the field that will be woven in:
@Embeddable public class LazyFulfillmentGroupImpl implements LazyFulfillmentGroup { @Parent protected FulfillmentGroup fulfillmentGroup; @ManyToOne(fetch = FetchType.LAZY, targetEntity = AddressImpl.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) protected Address address; @ManyToOne(fetch = FetchType.LAZY, targetEntity = PhoneImpl.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}) protected Phone phone; public FulfillmentGroup getFulfillmentGroup() { return fulfillmentGroup; } public void setFulfillmentGroup(FulfillmentGroup fulfillmentGroup) { this.fulfillmentGroup = fulfillmentGroup; } @Override public Address getAddress() { return address; } @Override public void setAddress(Address address) { this.address = address; } @Override public Phone getPhone() { return phone; } @Override public void setPhone(Phone phone) { this.phone = phone; } }
Create a weave class that will embed the class:
public class WeaveLazyFulfillmentGroupImpl implements LazyFulfillmentGroup { @Embedded public LazyFulfillmentGroupImpl embeddableLazyFulfillmentGroup; public LazyFulfillmentGroupImpl getEmbeddableLazyFulfillmentGroup(boolean assign) { LazyFulfillmentGroupImpl temp = embeddableLazyFulfillmentGroup; if (temp == null) { temp = new LazyFulfillmentGroupImpl(); if (assign) { embeddableLazyFulfillmentGroup = temp; } } if (temp.getFulfillmentGroup() == null) { temp.setFulfillmentGroup((FulfillmentGroup) this); } return temp; } @Override public Address getAddress() { return getEmbeddableLazyFulfillmentGroup(false).getAddress(); } @Override public void setAddress(Address address) { getEmbeddableLazyFulfillmentGroup(true).setAddress(address); } @Override public Phone getPhone() { return getEmbeddableLazyFulfillmentGroup(false).getPhone(); } @Override public void setPhone(Phone phone) { getEmbeddableLazyFulfillmentGroup(true).setPhone(phone); } }
In CoreConfig
add the configuration needed to weave in the class:
@Merge(targetRef = "blMergedClassTransformers", early = true) public List<DirectCopyClassTransformer> mySequenceSkuPriceDataTierTransformers() { return Arrays.asList(new DirectCopyClassTransformer("Core") .addXformTemplate("org.broadleafcommerce.core.order.domain.FulfillmentGroupImpl", "com.pr.weave.WeaveLazyFulfillmentGroupImpl")); }