一般的做法
这种方法将Coherence数据网格应用于依赖于无法完全预加载到Coherence缓存中的数据库托管数据的JPA应用程序。 它可能无法预加载的一些原因包括超出Coherence筛选器功能集的极其复杂的查询,创建陈旧缓存的第三方数据库更新,依赖本机SQL查询,存储过程或触发器等等。 这不仅是本地L2高速缓存的选项,而且在不同节点上具有其他已配置的Coherence实例,您还将获得群集范围的JPA L2高速缓存。
细节
与许多缓存一样,这是一项只读的优化。 主键查询尝试首先从Coherence获取实体,如果不成功,将查询数据库,并用查询结果更新Coherence。 针对数据库执行非主键查询,并针对Coherence检查结果,以避免缓存实体的对象构建成本。 新查询的实体将放入Coherence。 写操作将更新数据库,如果成功提交,则将更新后的实体放入Coherence。 这种方法在Coherence文档中称为“网格缓存”。
付诸实践
如果您还没有这样做,请从上一篇博客文章开始,并准备您的环境 。 只有一件事,您需要进行更改。 对于这种情况,请返回GlassFish 3.0.1 / EclipseLink 2.0.1,因为CacheKey.getKey()方法存在问题。 2.0.1返回一个Vector ,而2.2.0返回一个Object 。 看到新的Oracle GlassFish Server 3.1支持ActiveCache,我希望此问题将在3.7 Coherence版本中得到修复。 但是直到那之前,您必须坚持使用旧的GF或EclipseLink。
无论如何,让我们使用您喜欢的IDE(例如GridCacheExample)创建一个新的Web项目。 添加所需的库(coherence.jar,toplink-grid.jar和eclipselink.jar)。 现在,让我们创建实体类,并向其添加额外的@CacheInterceptor批注:
...import oracle.eclipselink.coherence.integrated.cache.CoherenceInterceptor;
import org.eclipse.persistence.annotations.CacheInterceptor;...@Entity
@CacheInterceptor(value = CoherenceInterceptor.class)
public class Employee implements Serializable {...}
不要忘记添加@GeneratedValue(strategy = GenerationType.SEQUENCE),因为这与上一个示例相反。 完成此操作后,您必须将一致性配置添加到WEB-INF / classes文件夹。 您可以从教程开始( 示例2 )。 (请注意,其中有一个错字…重复的</ backing-map-scheme>标记)。 像配置普通的基于JPA的应用程序一样,配置persistence.xml。
<persistence-unit name="GridCacheExamplePU" transaction-type="JTA"><provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/coherence</jta-data-source><properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.logging.level" value="FINE" />
</properties></persistence-unit>
基本上就是这样。 现在,您可以测试新的L2缓存。 一个简单的servlet应该可以解决问题:
public class InsertServletPart3 extends HttpServlet {@PersistenceUnit(unitName = "GridCacheExamplePU")
EntityManagerFactory emf;@Resource
UserTransaction tx;...EntityManager em = emf.createEntityManager();tx.begin();// some loop magic
Employee employee = new Employee();employee.setFirstName("Markus");
employee.setLastName("Eisele");em.persist(employee);// some loop magic end
tx.commit();em.close();
如果您查看日志,则可以看到以下内容:
FEIN: INSERT INTO EMPLOYEE (LASTNAME, FIRSTNAME) VALUES (?, ?)bind => [Eisele, Markus]
...
FEIN: Coherence(Employee)::Put: 1 value: net.eisele.coherence.entities.Employee[ id=1 ]
...
基本上,这告诉您,实际的数据库插入是由您惯常的EclipseLink执行的。 之后,您会看到Employee对象以PK作为键被放置到名为Employee的Coherence Cache中。
如果现在对数据库发出查询
em.createQuery("select e from Employee e where e.lastName = :lastName").setParameter("lastName", "Eisele").getResultList();
您会看到以下内容:
FEIN: SELECT ID, LASTNAME, FIRSTNAME FROM EMPLOYEE WHERE (LASTNAME = ?)bind => [Eisele]
FEIN: Coherence(Employee)::Get: 1 result: net.eisele.coherence.entities.Employee[ id=1 ]
FEIN: Coherence(Employee)::Put: 1 value: net.eisele.coherence.entities.Employee[ id=1 ]
...
这告诉您,查询本身是针对数据库发出的,但结果针对Coherence进行了检查,以避免已经为缓存的实体构造对象。 新查询的实体将放入Coherence。 如果发出简单的PK查询:
em.find(Employee.class, 1);
输出更改为:
FEIN: Coherence(Employee)::Get: 1 result: net.eisele.coherence.entities.Employee[ id=1 ]
而且您根本看不到任何数据库查询。 就是这样:)您的缓存有效! 谢谢阅读。 敬请期待下一部分!
进一步阅读
- OTN方法:将一致性用作共享的L2缓存
- Oracle TopLink与Coherence Gird 11g第1版(11.1.1)集成指南
参考: 具有GlassFish和一致性的高性能JPA –第3部分,来自我们的JCG合作伙伴 Markus Eisele ,在“使用Java进行企业软件开发”博客中
- 具有GlassFish和一致性的高性能JPA –第1部分
- 具有GlassFish和一致性的高性能JPA –第2部分
- 在云中开发和测试
- Java EE中的配置管理
- 泄漏:Oracle WebLogic Server 12g
- Java EE6装饰器:在注入时装饰类
- Java教程和Android教程列表
翻译自: https://www.javacodegeeks.com/2011/11/in-this-third-part-of-my-four-part.html