gpt4 book ai didi

java - JPA/Eclipselink 缓存生命周期

转载 作者:搜寻专家 更新时间:2023-11-01 03:29:50 25 4
gpt4 key购买 nike

1.- 我正在使用 Glassfish 2.1 和 EcipseLink 2.0.0,所以实际上使用的是 JPA 1.0 规范,而且我有一个无状态 EJB,可以在其他事物中找到实体。据我所知,JPA 1.0 定义了一个在 Persistence Context 级别(无状态 EJB 的事务级别)工作的 L1 缓存,但我无法弄清楚为什么下一个代码在同一事务中打印“不相同的实例”。

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class EntityServiceBean implements EntityServiceLocal {
@PersistenceContext(unitName = "Model")
private EntityManager entityManager;
@Override
public <T> T find(Class<T> type, Object id) {
T entity = entityManager.find(type, id);
if(entity != entityManager.find(type, id)) {
System.out.println("Not same instance");
}
return entity;
}
....
}

我什至尝试过这个属性:

<property name="eclipselink.cache.type.default" value="Full"/>

在 persistence.xml 文件中,但做同样的事情。

2.- 如果可能的话,我真正想要实现的是对我的无状态 EJB 的多次调用返回相同的实例,换句话说,使用无状态 EJB 跨越事务和持久性上下文的 JPA 缓存生命周期,例如:

... // POJO class
EntityServiceLocal entityService = ...
Product pA = entityService.find(Product.class, 1l);
...
Product pB = entityService.find(Product.class, 1l);
System.out.println("Same instance?" + pA == pB); // TRUE

我读到许多 JPA 实现使用 L2 缓存(现在在 JPA 2.0 中定义),即使在 JPA 1.0 中也跨越多个持久性上下文,但我不知道是否误解了 L2 缓存概念和/或我遗漏了任何配置。

这可能吗?或者我该怎么做才能避免每分钟从数据库中读取超过 2 万个实体来更新需要它的实体?

最佳答案

I'm working Glassfish 2.1 with EcipseLink 2.0.0, so really using JPA 1.0 specification, and I have a stateless EJB that finds entities among other things. As far as i know JPA 1.0 defines a L1 cache that works at Persistence Context level (transaction level for stateless EJBs) but I can't figure out why the next code prints "Not same instance" if it's within the same transaction.

THIS 非常奇怪,对象身份绝对应该在 Java EE 上下文中的事务内维护。这在 JPA wiki book 中有很好的记录。 :

Object Identity

Object identity in Java means if two variables (x, y) refer to the same logical object, then x == y returns true. Meaning that both reference the same thing (both a pointer to the same memory location).

In JPA object identity is maintained within a transaction, and (normally) within the same EntityManager. The exception is in a JEE managed EntityManager, object identity is only maintained inside of a transaction.

So the following is true in JPA:

Employee employee1 = entityManager.find(Employee.class, 123);
Employee employee2 = entityManager.find(Employee.class, 123);
assert (employee1 == employee2);

This holds true no matter how the object is accessed:

Employee employee1 = entityManager.find(Employee.class, 123);
Employee employee2 = employee1.getManagedEmployees().get(0).getManager();
assert (employee1 == employee2);

In JPA object identity is not maintained across EntityManagers. Each EntityManager maintains its own persistence context, and its own transactional state of its objects.

So the following is true in JPA:

EntityManager entityManager1 = factory.createEntityManager();
EntityManager entityManager2 = factory.createEntityManager();
Employee employee1 = entityManager1.find(Employee.class, 123);
Employee employee2 = entityManager2.find(Employee.class, 123);
assert (employee1 != employee2);

Object identity is normally a good thing, as it avoids having your application manage multiple copies of objects, and avoids the application changing one copy, but not the other. The reason different EntityManagers or transactions (in JEE) don't maintain object identity is that each transaction must isolate its changes from other users of the system. This is also normally a good thing, however it does require the application to be aware of copies, detached objects and merging.

Some JPA products may have a concept of read-only objects, in which object identity may be maintained across EntityManagers through a shared object cache.

而且我无法在 Java SE 环境中重现 EclipseLink 2.0 的问题(在事务内和相同的 EntityManager 中)- 抱歉,我不会在 GF 2.1 下进行测试。

I even tried with the property: <property name="eclipselink.cache.type.default" value="Full"/> in the persistence.xml file, but does the same

没有什么可以为 L1 缓存“激活”。

What I would really like to achieve, if possible, is that multiple calls to my stateless EJB return the same instance, in other words span the JPA cache life across transactions and Persistence Contexts using stateless EJBs (...):

二级缓存确实是跨越多个事务和 EntityManagers 的缓存,大多数 JPA 提供程序都支持二级缓存。但是,虽然 L2 缓存会减少数据库命中率,但并非所有提供程序都保证对象身份。

例如,对于 Hibernate,默认情况下不启用 L2 缓存,并且您不会获得对象标识,因为 Hibernate 不会将实体本身放入缓存中。

使用 EclipseLink,L2 cache默认情况下启用,您将获得 object identity depending on the cache type .默认值为 SOFT-WEAK cache of size 100它确实保留了对象身份。虽然您可以非常精细地配置事物(深入到实体级别),但对于 distributed environment不管是否如此,默认情况下应该可以正常工作。

另见

关于java - JPA/Eclipselink 缓存生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3472819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com