如何使我的 pojo 具有事务性?

发布于 2024-08-05 16:06:43 字数 218 浏览 9 评论 0原文

我有一个多线程、多服务器 Web 应用程序,使用 hibernate 和 spring 使用 AOP 管理事务。问题是,我需要维护内存中的数据并使其与数据库的状态保持同步......本质上我正在实现内存中的缓存。

现在,有什么方法可以使我的内存中 pojo 事务性达到与 hibernate/spring 事务性相同的级别吗?我的服务调用分层了 30 个类,而且我永远不知道提交将发生在哪里。我有什么选择?

I have a multi-threaded, multi-server web application with hibernate and spring managing transactions with AOP. The problem is, I need to maintain in-memory data and keep it current with the state of the database...essentially I'm implementing an in-memory cache.

Now, is there any way to make my in-memory pojos transactional on the same level as the hibernate/spring transactionality? I have service calls layered 30 classes deep, and I never know where the commit will occur. What are my options?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ら栖息 2024-08-12 16:06:43

如果我很理解你的需求,那么在某些情况下你会问一些微妙的问题。让我尝试一个示例来检查我是否理解正确

  1. 线程T1读取缓存中的pojo P,得到版本P1。
  2. 线程T2读取缓存中的pojo P,得到版本P1。
  3. 线程T2启动事务,读取相同的pojo,修改创建版本P2的值。
  4. 线程T1读取缓存中的pojo P,仍然得到版本P1。这要求对于第 3 点,T2 收到版本 P1 的副本 P2,而不是同一个对象。
  5. 线程 T2 保存 P,T1 或 T2 没有任何变化,它们有不同的版本。
  6. 线程 T2 关闭事务:
    一个。如果回滚,T2 将使用 P1,就像 T1 一样。
    b.如果提交,T2 将继续使用 P2。但现在 T1 也必须使用 P2。

可见这是一个复杂的问题,不要小看它。
在理论层面上已经有很多问题需要解决(当你编码时你会遇到更多问题......)。
如果您想成功使用它,您的架构将需要非常清晰。
如果没有,你就会冒着精神理智的风险;-)

首先,你需要确保你真的想要这样的东西!


如果你真的想要那样..

我建议使用技术代码(AOP, ThreadLocal)来隐藏功能代码中的这种棘手的复杂性

  • 很可能你的提交/回滚已经通过AOP完成,所以这应该没有问题。

    很可能

  • 隐藏 P 实例的检索(有时是 Stored 缓存中的实例,有时是副本):使用名为 Store 的类来存储缓存中的值,有一个 Store 类型的 ThreadLocal 变量。我会为当前线程使用 ThreadLocal 变量:

    • Store 实例只能在事务 AOP 代码中更改,而不能在功能代码中更改
    • 您的功能代码使用当前的 ThreadLocal 实例来操作实体(保存等...)
    • 在事务之外时,ThreadLocal 实例是缓存的实例,我们称之为 CACHE。
    • 输入事务为当前线程设置不同的 ThreadLocal 实例;该类是 Store 的子类,它将根据您的要求返回缓存对象的副本;该类还会记住是否保存了某些内容(因此您需要使用此特殊 API 来保存它们,或者在常规保存 API 中通知这一点)
    • 回滚事务会丢弃 ThreadLocal 实例,为当前线程重新安装 CACHED 实例
    • 提交事务将获取 ThreadLocal 实例中所有记忆的数据库操作,应用它来修改 CACHED 实例,并为当前线程重新安装 CACHED 实例

If I understand well your need, you are asking something delicate, in some contexts. Let me try an example, to check if I understand correctly:

  1. Thread T1 reads pojo P in the cache, gets version P1.
  2. Thread T2 reads pojo P in the cache, gets version P1.
  3. Thread T2 starts transaction, read the same pojo, modify a value which creates version P2.
  4. 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.
  5. Thread T2 saves P, nothing changes for either T1 or T2, they have different versions.
  6. 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.

You can see that this is a complex issue, don't underestimate it.
There are many issues to be solved, on the theoretical level already (and you will have more when you code...).
Your architecture will need to be really clear, if you want to use it successfully.
If not, you risk your mental sanity ;-)

First, You need to make sure you really want something like that!


If you really want that ..

I suggest using technical code (AOP, ThreadLocal) to hide this tricky complexity from your functional code.

  • It is probable that your commit/rollback is already done via AOP, so this should be no problem.

  • To hide the retrieving of instances of P (sometimes the instance in the Stored cache, sometimes a copy) : Use a class called Store to store the values in the cache, have a ThreadLocal variable of type Store. I would use a ThreadLocal variable for your current thread:

    • the Store instance can only be changed in your transactional AOP code, not in your functional code
    • your functional code uses the current ThreadLocal instance for manipulating the entities (saving etc...)
    • when outside a transaction, the ThreadLocal instance is the cached one, let's call it CACHE.
    • entering a transaction sets a different ThreadLocal instance for current thread ; that class is a subclass of Store, that will return copies of the caches objects as you ask for them ; the class will also memorise if some are saved (so you need to save them using this special API, or notify this in your regular saving API)
    • rollbacking a transaction would throw away the ThreadLocal instance, reinstalling the CACHED one for current thread
    • commiting a transaction would take all memorized database operation in the ThreadLocal instance, apply that to modify the CACHED instance, and reinstall the CACHED instance for current thread
止于盛夏 2024-08-12 16:06:43

是否使用 Hibernate 的 二级缓存 不能满足您的要求? JBoss Cache 提供程序既是分布式的又是事务性的。

如果这对你不起作用,你就必须解释为什么以及你真正想要实现的目标是什么,以获得有意义的回应。

Does using Hibernate's 2nd level cache not satisfy your requirements? JBoss Cache provider is both distributed and transactional.

If that doesn't work for you, you'll have to explain why and what is it you're really trying to achieve in order to get meaningful responses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文