0

我将 eclipselink 与 Coherence 分布式缓存和关系数据库(Toplink Grid - Grid cache configuration)一起使用。现在,我正在尝试尽可能高效地执行缓存预热,以减少未来与数据库的连接数量。

我有一个非常简单的数据模型:与子实体(MagicCard)具有单向一对多关系的父实体(Person)

@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,但我想避免这种更改,因为它会对我系统的另一部分产生负面影响。

批处理和加载提示不是应该初始化父对象中的子对象吗?还是我做错了什么?有没有其他/更好的方法来实现这一目标?

提前致谢

4

0 回答 0