是否有 Hibernate 的可行替代方案?最好是不基于 JPA 的东西。

我们的问题是我们正在构建一个复杂的(例如,许多对象相互引用)有状态的 RIA 系统。似乎 Hibernate 主要设计用于一次性应用程序 - JSF 等。

问题主要在于延迟加载。由于在初始化和实际加载惰性集合之间可能有多个 HTTP 请求,因此每个事务一个会话是不可能的。长期会话(每个应用程序一个)也不能很好地工作,因为一旦事务遇到障碍并抛出异常,整个会话就会失效,因此延迟加载的对象就会中断。然后有各种各样的东西对我们不起作用(比如从初始化事务外部持久化数据的隐式数据)。

抛开我糟糕的解释不谈,最重要的是 Hibernate 有我们不喜欢的魔力。看起来TopLink 也好不到哪里去,它也是在EJB 之上编写的。

因此,我们最需要的是一个无状态的持久层(或者甚至是足够明亮的面向对象的数据库抽象层)。

有什么想法,还是我要的是不存在的东西?

编辑:对于我模棱两可的术语,我深表歉意,感谢大家的更正和富有洞察力的回答。那些纠正我的人,你们都对,我说的是JPA,不是EJB。


如果您正在寻找另一个 JPA 提供者(Hibernate 是其中之一),那么请查看EclipseLink它比 TopLink Essentials 的 JPA 1.0 参考实现功能更全面。事实上,EclipseLink 将成为 Glassfish V3 Final 附带的 JPA 2.0 参考实现。

JPA 很好,因为您可以在容器内部和外部使用它。我已经编写了使用 JPA 的 Swing 客户端,效果很好。它没有 EJB 2.0/2.1 带来的相同耻辱和 XML 包袱。

如果您正在寻找更轻量级的解决方案,那么ibatis就是您的最佳选择,我认为它是我为 Java 平台选择的持久性技术。它是轻量级的,依赖于 SQL(ORM 用户花费多少时间试图让他们的 ORM 产生好的 SQL 是令人惊讶的)并且完成了 JPA 所做的 90-95%(如果需要,包括相关实体的延迟加载)。

只是为了纠正几点:

  • JPA是EJB的持久层,不是建立在EJB之上;
  • 任何体面的 JPA 提供者都有大量的缓存正在进行,可能很难全部弄清楚(这将是“为什么简单性如此复杂?”的一个很好的例子)。除非你正在做一些你没有指出的事情,否则异常不应该成为你的托管对象的问题。运行时异常通常会回滚事务(如果您使用 Spring 的事务管理,谁不这样做呢?)。提供者将维护已加载或持久化对象的缓存副本。如果您想在实体管理器之外进行更新(需要显式缓存刷新或使用EntityManager.refresh()),这可能会有问题。

如前所述,JPA <> EJB,它们甚至没有关系。EJB 3 碰巧利用了 JPA,仅此而已。我们有很多使用 JPA 的东西,它们甚至无法接近运行 EJB。

你的问题不是技术,而是你的设计。

或者,我应该说,您的设计不容易适应几乎所有现代框架。

具体来说,您试图通过多个 HTTP 请求使事务保持活动状态。

自然地,大多数常见的习语是每个请求本身就是一个或多个事务,而不是每个请求都是更大事务的一部分。

当您在同一讨论中使用术语“无状态”和“事务”时,也存在明显的混淆,因为事务本质上是有状态的。

您的大问题只是手动管理您的交易。

如果您的交易发生在多个 HTTP 请求上,并且这些 HTTP 请求恰好“非常快”地一个接一个地运行,那么您真的不应该遇到任何真正的问题,除了您必须确保您的 HTTP请求使用相同的数据库连接以利用数据库事务设施。

也就是说,简单来说,您获得到数据库的连接,将其填充到会话中,并确保在事务期间,您的所有 HTTP 请求不仅通过相同的会话,而且以这种方式实际连接仍然有效。具体来说,我不相信现成的 JDBC 连接实际上可以在从一台机器到另一台机器的故障转移或负载平衡中幸存下来。

所以,简单地说,如果你想使用数据库事务,你需要确保你使用相同的数据库连接。

现在,如果您长时间运行的事务中有“用户交互”,即您启动数据库事务并等待用户“做某事”,那么很简单,该设计完全错误。你不想那样做,因为长期交易,尤其是在交互式环境中,简直就是坏事。就像“穿越溪流”一样糟糕。不要这样做。批量交易不同,但交互式长期交易是不好的。

您希望使您的交互式事务尽可能短。

Now, if you can NOT ensure you will be able to use the same DB connection for your transaction, then, congratulations, you get to implement your own transactions. That means you get to design your system and data flows as if you have no transactional capability on the back end.

That essentially means that you will need to come up with your own mechanism to "commit" your data.

A good way to do this would be where you build up your data incrementally into a single "transaction" document, then feed that document to a "save" routine that does much of the real work. Like, you could store a row in the database, and flag it as "unsaved". You do that with all of your rows, and finally call a routine that runs through all of the data you just stored, and marks it all as "saved" in a single transaction mini-batch process.

Meanwhile, all of your other SQL "ignores" data that is not "saved". Throw in some time stamps and have a reaper process scavenging (if you really want to bother -- it may well be actually cheaper to just leave dead rows in the DB, depends on volume), these dead "unsaved" rows, as these are "uncomitted" transactions.

它并不像听起来那么糟糕。如果你真的想要一个无状态的环境,就像我听起来的那样,那么你需要做这样的事情。

请记住,在所有这一切中,持久性技术确实与它无关。问题是你如何使用你的交易,而不是技术。


我认为你应该看看apache cayenne,它是“大”框架的一个很好的替代品。凭借其体面的建模器,良好的文档可以缩短学习曲线。


我去年看过SimpleORM,对其轻量级的无魔法设计印象深刻。现在似乎有第 3 版,但我对那个没有任何经验。


Ebean ORM ( http://www.avaje.org )

它是一个使用起来更简单、更直观的 ORM。

  • 使用 JPA 注释进行映射(@Entity、@OneToMany 等)
  • 无会话 API - 无 Hibernate 会话或 JPA 实体管理器
  • 延迟加载才有效
  • 部分对象支持以获得更高的性能
  • 通过“Autofetch”进行自动查询调整
  • 弹簧集成
  • 大型查询支持
  • 对批处理的强大支持
  • 后台抓取
  • DDL生成
  • 如果你愿意,你可以使用原始 SQL(和 Ibatis 一样好)
  • LGPL许可

  • 抢。


BEA Kodo(以前称为 Solarmetric Kodo)是另一种选择。它支持 JPA、JDO 和 EJ3。它是高度可配置的,可以支持积极的预取、分离/附加对象等。

不过,根据您的描述,Toplink 应该能够处理您的问题。大多数情况下,听起来您需要能够在请求开始和结束时从持久层附加/分离对象。


仅供参考,为什么 OP 的设计是他最大的问题:跨越多个用户请求的事务意味着您可以在给定时间拥有与连接到您的应用程序的用户一样多的打开事务 - 一个事务使连接保持忙碌直到它被提交/回滚。对于数千个同时连接的用户,这可能意味着数千个连接。大多数数据库不支持这一点。


Hibernate 和 Toplink (EclipseLink) 都不是基于 EJB,它们都是 POJO 持久性框架 (ORM)。

同意前面的回答:iBatis是ORM框架的一个很好的替代品:完全控制sql,有很好的缓存机制。


另一个选项是 Torque,我并不是说它比上面提到的任何选项都好,只是说它是另一个值得考虑的选项。它现在已经很老了,但可能符合您的一些要求。

力矩