如上所述,JPA并不等同于EJB,它们甚至没有关联。EJB 3碰巧利用了JPA,但仅限于此。我们有许多使用JPA的东西,与运行EJB毫不相干。
你的问题不在技术方面,而在于你的设计。
或者说,你的设计几乎不适合任何现代框架。
具体来说,你试图在多个HTTP请求之间保持事务活动。
自然而然地,每个常见的习语都是每个请求本身都是一个或多个事务,而不是每个请求都是大事务的一部分。
当你在同一讨论中使用“无状态”和“事务”这个词汇时,也会存在明显的混淆,因为事务本质上是具有状态的。
你的主要问题在于手动管理事务。
如果你的事务在多个HTTP请求中发生,并且这些HTTP请求恰好相继快速运行,则你实际上不应该遇到任何实际问题,除非你必须确保你的HTTP请求使用相同的DB连接以利用数据库的事务功能。
也就是说,简单来说,你需要获取到DB连接,在会话中存储它,并确保在事务期间,所有的HTTP请求都通过同一个会话进行,而且连接实际上仍然有效。具体而言,我不认为有一个现成的JDBC连接能够从一个机器进行故障转移或负载平衡。
因此,简单地说,如果你想使用DB事务,你需要确保使用相同的DB连接。
现在,如果你的长时间运行的事务中有“用户交互”,例如,你开始DB事务,并等待用户“做某些事情”,那么,简单地说,该设计就是错误的。在交互式环境中,长时间运行的事务,尤其是具有用户交互的事务,是非常糟糕的。像“Crossing The Streams”这样糟糕。不要这样做。批处理事务是不同的,但是交互式的长时间运行的事务是不好的。
你需要使你的交互式事务尽可能短暂。
现在,如果你不能确保能够为你的事务使用相同的DB连接,那么恭喜你,你需要实现自己的事务。这意味着你需要设计你的系统和数据流程,就好像后端没有任何事务能力一样。
这基本上意味着你需要想出自己的机制来“提交”你的数据。
一个很好的方法是逐步构建你的数据,形成单个的“事务”文档,然后将该文档提供给执行大部分真正工作的“保存”例程。例如,你可以将一行存储在数据库中,并将其标记为“未保存”。你对所有行都这样做,最后调用一个例程,运行通过你刚刚存储的所有数据,并以单个事务小批量过程将其全部标记为“已保存”。
同时,您的其他SQL语句会“忽略”未“保存”的数据。如果加入一些时间戳并启用收割进程(如果您真的想要打扰——可能更便宜的方法是将死行保留在数据库中,这取决于数量),则可以清除这些“未保存”的死行,因为这些是“未提交”的事务。
这并没有听起来那么糟糕。如果您真的想要一个无状态环境,这正是我所想的,那么您需要像这样做一些事情。
请注意,在所有这些中,持久化技术实际上与此无关。问题在于如何使用事务,而不是技术本身。