实现基于JPA的持久性的服务层可以从JPA提供程序透明管理的二级缓存(例如Hibernate,Toplink / Toplink Essentials等)中获得巨大利润。当激活此缓存时,它会在第一次从数据库加载时保留持久类的实例。可能存在特定于供应商的扩展来配置缓存行为。
JPA标准还通过使用时间戳或版本字段来支持乐观锁定,该字段用于避免在发生并发更新时数据损坏。由于此机制依赖于数据库中包含的数据,因此当其他应用程序或服务想要更新数据时也可以使用它 - 只需在更新中包含记录的版本字段即可。
当谈到缓存时,行为似乎是 JPA提供商(至少Toplink Essentials)没有注意到数据库中的更改不使用EntityManager执行。
这是否真的是默认行为,更新/无效JPA提供程序缓存的责任取决于应用程序?如果是的话,这似乎与大多数数据库被许多不同的应用程序使用的事实相反。
答案 0 :(得分:3)
这种行为对于Hibernate(19.2. The Second Level Cache)也是如此:
请注意,缓存不知道其他应用程序对持久性存储所做的更改。但是,它们可以配置为定期使缓存的数据到期。
这听起来很合理。如果此缓存不使用缓存,您的缓存应该如何知道另一个应用程序所做的任何更改?缓存/ JPA提供程序的唯一可能性是监视数据库(所有表,所有数据)以进行更改并相应地更新。这不太可行。
我还读到,由于上述原因,当多个应用程序更改数据库中的相同数据时,强烈建议不要使用二级缓存。
答案 1 :(得分:1)
我们已成功使用PostgreSQL LISTEN / NOTIFY来保持我们的第二级(客户端)缓存最新。从PostgreSQL 9.0开始,NOTIFY也支持指定有效负载。我们用C ++实现它并使用ODBC,但JPA / JDBC也提供了这样的功能。
该过程比较复杂,但提供比刷新完整缓存或根本不使用缓存更好的性能,特别是如果某些关系相对较少更新。
程序的本质是:
LISTEN
)"MYTABLE"
MYTABLE
上的插入/更新/删除触发器将更改(例如事件时间戳,操作码和主键)记录到表MYTABLE_NY
中并发送通知:NOTIFY MYTABLE
EVENT_TIMESTAMP > last_cache_refresh
中的最新更改(例如MYTABLE_NY
)。session.evict()
或cache.evictEntity()
结果是一个缓存实现,它包含在数据库服务器上关闭的任何事务的一秒内的最新数据。我们主要将它用于AutoComplete而没有任何问题,即它甚至可用于高速交互使用缓存数据。
如果感兴趣,我可以提供一些代码示例。