5

I am trying to enable Hibernate's 2nd level cache but cannot avoid multiple queries being issued for OneToOne relations.

My models are:

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Business {

    @OneToOne(mappedBy = "business", cascade = {CascadeType.REMOVE}, fetch = FetchType.EAGER)
    private Address address;
}

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Address {

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "business_id", unique = true, nullable = false, foreignKey = @ForeignKey(name = "fk_business_id"))
    private Business business;
}

When I run session.get(Business.class, id) with the Business with id id in the cache, no query is issued for loading Business but it does for Address.

I understand that Address is the relation owner and that in the Business cache entry there's no Address.id information, but wouldn't it be possible to solve this problem by applying the same mechanism as *ToMany relations does, creating a new cache region for each field? Assuming Business 1 is related to Address 2, there would be the following regions and entries in my cache after a first load:

Business
  Business#1         -> [business model]
Business.address
  Business.address#1 -> [2]
Address
  Address#2          -> [address model]

I have tried to make it work by annotating Address.business with @NaturalId and the Address class with @NaturalIdCache. The cache region is created and populated but session.get(Business.class, id) does not use it.

My Business model has many more OneToOne relations whose foreign key is on the other side (not the Business) and we must list several at a time so the database server has to process dozens of queries per HTTP request.

I have read the Hibernate's User Guide, Vlad Mihalcea's explanation on 2LC and its in-memory dehydrated format, Baeldung's explanation and several other StackOverflow answers and cannot find a way to solve this.

Heits
  • 665
  • 5
  • 9

0 Answers0