2014-03-29 37 views
3

EntityManager为检索到的对象维护第一级缓存,但是如果您想要创建和关闭每个事务的entityManager的线程安全应用程序。JPA和第一级缓存,什么是重点?

那么,如果这些实体创建并关闭每个事务,那么级别1高速缓存的重点是什么?或者,如果您在单线程中工作,entityManager缓存是否可用?

+1

我想你应该受益的读一本书像[临JPA 2:掌握了Java™持久性API(http://www.amazon.com/Pro-JPA-Mastering-Persistence-Technology/dp/1430219564/ REF = sr_1_1?IE = UTF8&QID = 1396104703&SR = 8-1 =关键字+专业+ JPA 2.1 +主控+的+的Java持久性+ + API)。阅读本书,您将准备好进行[Java EE 6 Java持久性API开发人员认证专家考试](https://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=5001&get_params= p_exam_id:1Z0-898)。这将是你很快回答问题。 –

+0

感谢您的时间。 – vach

回答

3

第一级缓存有其他用途。它基本上是JPA放置从数据库中检索到的实体的上下文。

性能

因此,要启动说明明显,它避免了检索时已经被检索它的事务处理过程中充当某种形式的高速缓存和提高性能的记录。另外,请考虑延迟加载。你怎么能实现它没有缓存来记录已经被加载的实体?

循环关系

此缓存的目的是适宜的ORM框架的实现至关重要。在面向对象的语言中,对象图具有循环关系是很常见的。例如,具有Employee对象和这些Employee对象的Department属于一个Department。

如果没有上下文(又名为Unit of Work),那么很难记录已经有ORMed的记录,并且最终会创建新的对象,并且在这种情况下,甚至可能会以无限循环。

保持变化的轨迹:提交和回滚

而且,这种情况下会跟踪你的对象,使他们可以持续或在事务结束时在以后的某个点回滚的变化。如果没有像这样的缓存,您将不得不在数据库中立即刷新对数据库的更改,然后无法回滚,也无法优化将数据刷新到商店的最佳时机。

对象标识

对象的身份也是ORM框架至关重要。也就是说,如果您检索员工ID 123,那么如果您有时需要该员工,则应该始终获得相同的对象,而不是包含相同数据的新对象。

这种类型的缓存是不被多个线程共享,如果是这样,你会妥协的性能和强迫大家甚至是支付罚款时,他们可能只是一个单线程的解决方案的罚款。除了事实上,你会最终得到一个更复杂的解决方案,就像用火箭筒杀死苍蝇一样。

这就是为什么如果你需要的是一个共享缓存,那么你实际上需要一个二级缓存,并且还有一些实现。

+0

感谢您的回答。现在假设我们有两个实体,并且em1已经加载了Entity1的实例和来自thread1的一些依赖的Entity2实例。现在em2正在尝试从thread2加载相同的Entity2实例。这里应该发生什么? em2应该等待em1关闭,否则我会得到已经在em1中的对象的异常?你可以回答这里http://stackoverflow.com/questions/22732416/regarding-thread-safety-and-jpa-entitymanager – vach

4

关键是要有一个像你期望的那样工作的应用程序,并且这不会太慢。我们举个例子:

Order order = em.find(Order.class, 3L); 
Customer customer = em.find(Customer.class, 5L); 
for (Order o : customer.getOrders()) { // line A 
    if (o.getId().longValue == 3L) { 
     o.setComment("hello"); // line B 
     o.setModifier("John"); 
    } 
} 

System.out.println(order.getComment)); // line C 

for (Order o : customer.getOrders()) { // line D 
    System.out.println(o.getComment()); // line E 
} 

在A行,JPA执行一个SQL查询来加载客户的所有订单。

在C行,你期望打印什么? null"hello"?您希望打印“hello”,因为您在B行修改的订单具有与第一行加载的订单相同的ID。没有第一级缓存,这是不可能的。

在D行,您不希望订单再次从数据库中加载,因为它们已经在A行加载。如果没有第一级缓存,这是不可能的。

在E行,您希望再次打印订单3的“hello”。如果没有第一级缓存,这将是不可能的。

在B行,您不希望执行更新查询,因为可能会有许多后续修改(如下一行)到同一个实体。因此,您希望尽可能晚地将这些修改写入数据库,在交易结束时一次性完成。没有第一级缓存,这是不可能的。

相关问题