JPA/Eclipselink缓存寿命 [英] JPA/Eclipselink cache life span

查看:94
本文介绍了JPA/Eclipselink缓存寿命的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1.-我正在将Glassfish 2.1与EcipseLink 2.0.0一起使用,因此实际上使用的是JPA 1.0规范,并且我有一个无状态EJB,可用于查找实体.据我所知,JPA 1.0定义了一个L1高速缓存,该高速缓存可以在持久性上下文级别(无状态EJB的事务级别)下工作,但我不知道为什么下一个代码在同一事务中打印不同实例". >

1.- 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.

@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;
    }
    ....
}

我什至尝试使用该属性:

I even tried with the property:

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

在persistence.xml文件中,但相同.

in the persistence.xml file, but does the same.

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

2.- 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, for example:

... // 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缓存的概念和/或我错过了任何配置.

I read that many JPA implementations make use of a L2 cache(now defined in JPA 2.0) that spans multiple Persistence Contexts even with JPA 1.0 but I don't know if misunderstood the L2 cache concept and/or I'm missing any configuration.

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

Is this possible? Or what can i do to avoid reading more than 20k entities from the DB every minute to update the ones that need it?

推荐答案

我正在将Glassfish 2.1与EcipseLink 2.0.0一起使用,因此实际上使用的是JPA 1.0规范,并且我有一个无状态EJB,可用于查找实体.据我所知,JPA 1.0定义了一个L1缓存,该缓存可以在持久性上下文级别(无状态EJB的事务级别)下工作,但是我不知道为什么下一个代码在同一事务中打印不相同的实例".

THIS 非常奇怪,在Java EE上下文中的事务内部一定要维护对象标识. JPA Wiki书:

THIS is extremely weird, object identity should definitely be maintained inside a transaction in a Java EE context. This is very well documented in the JPA wiki book:

对象身份

Java中的对象身份意味着如果两个 变量(x,y)指的是相同的 逻辑对象,则x == y返回 真的.意思是两者都引用了 同一件事(都是指向同一事物的指针) 内存位置).

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).

在JPA中,对象标识得以维护 在交易中,以及(通常) 在同一EntityManager中.这 例外是在JEE托管中 EntityManager,仅对象标识 保持在交易内部.

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.

因此,在JPA中,以下内容是正确的:

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

在JPA中,对象标识不是 跨EntityManager维护.每个 EntityManager保持自己的状态 持久性上下文及其自身 对象的事务状态.

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

因此,在JPA中,以下内容是正确的:

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

对象身份通常是一个很好的选择 东西,因为它避免了你的 应用程序管理多个副本 对象,并避免应用 更改一个副本,但不更改另一个副本. EntityManagers不同的原因还是 交易(在JEE中)不维护 对象身份是每个 交易必须隔离其更改 来自系统的其他用户.这 通常也是一件好事,但是 它确实需要该应用程序是 知道副本,分离的物体以及 合并.

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.

某些JPA产品可能有一个概念 只读对象,其中对象 身份可以保持跨 通过共享对象的EntityManager 缓存.

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环境中(在事务内和相同的EntityManager中)重现EclipseLink 2.0的问题-抱歉,我不会在GF 2.1下进行测试.

And I couldn't reproduce the problem with EclipseLink 2.0 in a Java SE environment (within a transaction and the same EntityManager) - sorry I won't test under GF 2.1.

我什至尝试使用persistence.xml文件中的属性:<property name="eclipselink.cache.type.default" value="Full"/>,但效果相同

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

L1缓存没有什么可激活"的.

There is nothing to "activate" for the L1 cache.

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

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 (...):

L2缓存确实是跨多个事务的缓存,并且EntityManagers和大多数JPA提供程序都支持L2缓存.但是,尽管L2缓存将减少数据库命中率,但并非所有提供程序都可以保证对象标识.

A L2 cache is indeed a cache that spans multiple transactions and EntityManagers and L2 caching is supported by most JPA providers. But while L2 caching will reduce database hits, object identity is not guaranteed with all providers.

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

For example, with Hibernate, the L2 cache isn't enabled by default and you won't get object identity as Hibernate doesn't put the entities themselves in cache.

使用EclipseLink,默认情况下启用L2 缓存,并且您会根据缓存类型对象身份.默认值为大小为100的SOFT-WEAK缓存,并且它确实保留了对象身份.虽然您可以很好地配置(到实体级别),但对于分布式环境不管是否,默认情况下都可以正常工作.

With EclipseLink, L2 cache is enabled by default and you'll get object identity depending on the cache type. The default is the SOFT-WEAK cache of size 100 and it does preserve object identity. While you can configure things very finely (down to the entity level), for distributed environment or not, things should work by default.

  • How to Use the Persistence Unit Properties for Caching
  • Using EclipseLink JPA Extensions for Entity Caching

这篇关于JPA/Eclipselink缓存寿命的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆