Прогрев eclipselink и кэша когерентности: дочерние элементы не инициализируются
Я использую eclipselink вместе с распределенным кешем Coherence и реляционной базой данных (конфигурация Toplink Grid - Grid cache). Прямо сейчас я пытаюсь выполнить разогрев кеша настолько эффективно, насколько это возможно, сокращая количество будущих подключений к базе данных.
У меня очень простая модель данных: родительский объект (Person) с однонаправленным отношением "один ко многим" к объекту childs (MagicCard)
@Entity
@Customizer(GridCacheCustomizer.class)
public class Person implements Serializable {
@Id
private int Id;
@Version
protected int version;
private String surname;
private String name;
@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY , orphanRemoval=true )
@CascadeOnDelete
@JoinColumn(name="person_id_ref")
private List<MagicCard> cardList;
}
@Entity
@Customizer(GridCacheCustomizer.class)
public class MagicCard implements Serializable {
@Id
private int Id;
private String descr;
@Version
protected int version;
}
Чтобы выполнить прогрев кеша, я делаю запрос, используя пакетную выборку. Таким образом, я избегаю выполнения выбора базы данных N+1.
Query q = em.createQuery("select p from Person p");
q.setHint(QueryHints.BATCH, "p.cardList");
q.setHint(QueryHints.BATCH_TYPE, "IN");
q.setHint(QueryHints.LOAD_GROUP_ATTRIBUTE, "cardList");
List<Person> people = (List<Person>) q.getResultList();
который переводит во время выполнения в:
[EL Fine]: sql: Connection(1099217286)--SELECT ID, NAME, SURNAME, VERSION FROM PERSON
[EL Fine]: sql: Connection(1099217286)--SELECT ID, DESCR, VERSION, person_id_ref FROM MAGICCARD WHERE (person_id_ref IN (?,?,?,?))
bind => [1, 2, 3, 4]
Похоже, что этот поиск правильно заполняет кэши Coherence для обоих объектов. Следующий журнал взят из примера с 4 людьми (с 4,3,1 и 0 карточками соответственно):
[EL Fine]: cache: Coherence(Person)::Get: [1, 2, 3, 4] result size: 4
[EL Fine]: cache: Coherence(Person)::ConditionalPut: 1 value: entities.Person hashcode: 558082331
[EL Fine]: cache: Coherence(MagicCard)::Get: [3, 1, 2, 4, 5, 6, 7, 8] result size: 8
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 3 value: entities.MagicCard hashcode: 321885278
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 1 value: entities.MagicCard hashcode: 1206609130
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 2 value: entities.MagicCard hashcode: 1405610448
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 4 value: entities.MagicCard hashcode: 948640159
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 5 value: entities.MagicCard hashcode: 2122449463
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 6 value: entities.MagicCard hashcode: 714661629
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 7 value: entities.MagicCard hashcode: 905115332
[EL Fine]: cache: Coherence(MagicCard)::ConditionalPut: 8 value: entities.MagicCard hashcode: 127827822
[EL Fine]: cache: Coherence(Person)::ConditionalPut: 2 value: entities.Person hashcode: 1268451305
[EL Fine]: cache: Coherence(Person)::ConditionalPut: 3 value: entities.Person hashcode: 1535800224
[EL Fine]: cache: Coherence(Person)::ConditionalPut: 4 value: entities.Person hashcode: 164901111
*****************
cache : class com.tangosol.coherence.component.util.SafeNamedCache -- Person
.------- cache Person size 4
| KEY : 1 - VALUE TYPE : oracle.eclipselink.coherence.integrated.cache.wrappers.entities.Person_Wrapper
| KEY : 3 - VALUE TYPE : oracle.eclipselink.coherence.integrated.cache.wrappers.entities.Person_Wrapper
| KEY : 4 - VALUE TYPE : oracle.eclipselink.coherence.integrated.cache.wrappers.entities.Person_Wrapper
| KEY : 2 - VALUE TYPE : oracle.eclipselink.coherence.integrated.cache.wrappers.entities.Person_Wrapper
'--------------------
cache : class com.tangosol.coherence.component.util.SafeNamedCache -- MagicCard
.------- cache MagicCard size 8
| KEY : 1 - VALUE TYPE : Entities.MagicCard
| KEY : 7 - VALUE TYPE : Entities.MagicCard
| KEY : 3 - VALUE TYPE : Entities.MagicCard
| KEY : 5 - VALUE TYPE : Entities.MagicCard
| KEY : 4 - VALUE TYPE : Entities.MagicCard
| KEY : 6 - VALUE TYPE : Entities.MagicCard
| KEY : 2 - VALUE TYPE : Entities.MagicCard
| KEY : 8 - VALUE TYPE : Entities.MagicCard
'--------------------
*****************
Затем я пытаюсь найти (используя EntityManager) конкретного человека или конкретную карту
System.err.println("*** FINDING PERSON WITH ID=1 ***");
Person p = em1.find(Person.class, id);
System.out.println("[PERSON] " + p.toString());
и поиск в кэше успешно выполняется, как и ожидалось:
*** FINDING PERSON WITH ID=1 ***
[EL Fine]: cache: Coherence(Person)::Get: 1 result: entities.Person hashcode: 2132249404
[PERSON] Person [Id=1, name=x, surname=y]
однако, когда я пытаюсь найти карточки человека, eclipselink необходимо выполнить дополнительный выбор базы данных (я думал, что я бы избежал их с пакетной выборкой (?)):
System.err.println("*** FINDING CARDS FROM PERSON WITH ID=1 ***");
Person p = em1.find(Person.class, id);
List<MagicCard> cards = p.getMagicCardList();
System.out.println(cards.size() + " cards found:\n");
---
[EL Fine]: cache: Coherence(Person)::Get: 1 result: entities.Person hashcode: 138084761
[EL Fine]: sql: Connection(278533322)--SELECT ID, DESCR, VERSION FROM MAGICCARD WHERE (person_id_ref = ?)
bind => [1]
[EL Fine]: cache: Coherence(MagicCard)::Get: [3, 1, 2, 4] result size: 4
4 cards found
Я ожидал, что он получит список карточек из кэша когерентности, а не из базы данных, так как ранее я заполнил первую карточками всех. Единственный способ заставить его работать так, как я хотел, - это поменять @OneToMany FetchType на EAGER, но я бы хотел избежать этого изменения, так как оно оказывает негативное влияние на другую часть моей системы.
Разве советы по загрузке и загрузке не должны были инициализировать дочерние объекты в родительском объекте? Или я что-то не так делаю? Есть ли другой / лучший способ добиться этого?
заранее спасибо