我有一个多线程、多服务器的 Web 应用程序,它使用 hibernate 和 spring 使用 AOP 管理事务。问题是,我需要维护内存中的数据并使其与数据库的状态保持同步...本质上,我正在实现内存中的缓存。
现在,有什么方法可以使我的内存中 pojos 事务性与 hibernate/spring 事务性处于同一级别?我有 30 个类深层次的服务调用,我永远不知道提交将发生在哪里。我有哪些选择?
最佳答案
如果我很好地理解您的需求,那么在某些情况下您是在问一些微妙的问题。让我尝试一个示例,以检查我是否理解正确:
- Thread T1 reads pojo P in the cache, gets version P1.
- Thread T2 reads pojo P in the cache, gets version P1.
- Thread T2 starts transaction, read the same pojo, modify a value which creates version P2.
- Thread T1 reads pojo P in the cache, still gets version P1. This requires that for point 3, T2 received a copy P2 of version P1, not the same object.
- Thread T2 saves P, nothing changes for either T1 or T2, they have different versions.
- Thread T2 closes the transaction:
a. if rollback, T2 will then use P1, as T1 does.
b. if commit, T2 will continue using P2. But now T1 must use P2 also.
可以看出这是一个复杂的问题,不要小看它。 在理论层面上已经有很多问题需要解决(当你编码时你会遇到更多......)。 如果你想成功地使用它,你的架构需要非常清晰。 如果没有,你会冒着精神错乱的风险 ;-)
首先,您需要确保您真的想要这样的东西!
如果你真的想要那个..
我建议使用技术代码(AOP、ThreadLocal)从您的功能代码中隐藏这种棘手的复杂性。
很可能您的提交/回滚已经通过 AOP 完成,所以这应该没有问题。
要隐藏 P 实例的检索(有时是存储缓存中的实例,有时是副本):使用一个名为 Store 的类将值存储在缓存中,有一个 Store 类型的 ThreadLocal 变量。我会为您当前的线程使用一个 ThreadLocal 变量:
- Store 实例只能在您的事务性 AOP 代码中更改,不能在您的功能代码中更改
- 您的功能代码使用当前的 ThreadLocal 实例来操作实体(保存等...)
- 当在事务之外时,ThreadLocal 实例是缓存的实例,我们称它为缓存。
- entering a transaction 为当前线程设置一个不同的 ThreadLocal 实例;该类是 Store 的子类,它将在您请求时返回缓存对象的副本;该类还将记住是否保存了一些内容(因此您需要使用这个特殊的 API 来保存它们,或者在您的常规保存 API 中通知这一点)
- 回滚事务会丢弃 ThreadLocal 实例,为当前线程重新安装 CACHED 实例
- 提交事务将采用 ThreadLocal 实例中所有存储的数据库操作,应用它来修改 CACHED 实例,并为当前线程重新安装 CACHED 实例
关于hibernate - 如何使我的 pojo 具有事务性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1461039/