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"));
}