JPA通过并发访问数据库来缓存最新版本

时间:2009-10-09 10:58:36

标签: database jpa caching concurrency

实现基于JPA的持久性的服务层可以从JPA提供程序透明管理的二级缓存(例如Hibernate,Toplink / Toplink Essentials等)中获得巨大利润。当激活此缓存时,它会在第一次从数据库加载时保留持久类的实例。可能存在特定于供应商的扩展来配置缓存行为。

JPA标准还通过使用时间戳或版本字段来支持乐观锁定,该字段用于避免在发生并发更新时数据损坏。由于此机制依赖于数据库中包含的数据,因此当其他应用程序或服务想要更新数据时也可以使用它 - 只需在更新中包含记录的版本字段即可。

当谈到缓存时,行为似乎是 JPA提供商(至少Toplink Essentials)没有注意到数据库中的更改不使用EntityManager执行。

这是否真的是默认行为,更新/无效JPA提供程序缓存的责任取决于应用程序?如果是的话,这似乎与大多数数据库被许多不同的应用程序使用的事实相反。

2 个答案:

答案 0 :(得分:3)

这种行为对于Hibernate(19.2. The Second Level Cache)也是如此:

  

请注意,缓存不知道其他应用程序对持久性存储所做的更改。但是,它们可以配置为定期使缓存的数据到期。

这听起来很合理。如果此缓存不使用缓存,您的缓存应该如何知道另一个应用程序所做的任何更改?缓存/ JPA提供程序的唯一可能性是监视数据库(所有表,所有数据)以进行更改并相应地更新。这不太可行。

我还读到,由于上述原因,当多个应用程序更改数据库中的相同数据时,强烈建议不要使用二级缓存。

答案 1 :(得分:1)

我们已成功使用PostgreSQL LISTEN / NOTIFY来保持我们的第二级(客户端)缓存最新。从PostgreSQL 9.0开始,NOTIFY也支持指定有效负载。我们用C ++实现它并使用ODBC,但JPA / JDBC也提供了这样的功能。

该过程比较复杂,但提供比刷新完整缓存或根本不使用缓存更好的性能,特别是如果某些关系相对较少更新。

程序的本质是:

  1. 针对特定事件(例如LISTEN
  2. 缓存实施"MYTABLE"
  3. MYTABLE上的插入/更新/删除触发器将更改(例如事件时间戳,操作码和主键)记录到表MYTABLE_NY中并发送通知:NOTIFY MYTABLE
  4. 缓存实施接收通知并检查EVENT_TIMESTAMP > last_cache_refresh中的最新更改(例如MYTABLE_NY)。
  5. 对于每个事件,它从缓存中删除给定的实例。如果是Hibernate,请使用session.evict()cache.evictEntity()
  6. 结果是一个缓存实现,它包含在数据库服务器上关闭的任何事务的一秒内的最新数据。我们主要将它用于AutoComplete而没有任何问题,即它甚至可用于高速交互使用缓存数据。

    如果感兴趣,我可以提供一些代码示例。