6

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

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

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

撇开我拙劣的解释不谈,最重要的是 Hibernate 做了我们不喜欢的魔法。似乎 TopLink 也好不到哪里去,它也是在 EJB 之上编写的。

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

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

编辑:我为我模棱两可的术语感到抱歉,感谢大家的更正和有见地的回答。那些纠正我的人,你们都是正确的,我的意思是JPA,而不是EJB。

4

11 回答 11

7

如果您正在寻找另一个 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()),这可能会出现问题。
于 2009-01-05T13:54:06.107 回答
6

如前所述,JPA <> EJB,它们甚至不相关。EJB 3 恰好利用了 JPA,但仅此而已。我们有很多使用 JPA 的东西,它们甚至无法运行 EJB。

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

或者,我应该说,您的设计几乎不适合任何现代框架。

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

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

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

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

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

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

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

现在,如果您的长时间运行的事务中包含“用户交互”,即您启动数据库事务并等待用户“做某事”,那么,很简单,这种设计都是错误的。您不想这样做,因为长期事务,尤其是在交互式环境中,简直就是坏事。就像“过河”一样糟糕。不要这样做。批量事务是不同的,但交互式长寿命事务是不好的。

您希望使您的交互式交易尽可能地短命。

现在,如果您不能确保您将能够为您的事务使用相同的数据库连接,那么恭喜您,您可以实现自己的事务。这意味着您可以设计您的系统和数据流,就好像您在后端没有事务能力一样。

这实质上意味着您将需要提出自己的机制来“提交”您的数据。

做到这一点的一个好方法是您将数据增量构建到单个“事务”文档中,然后将该文档提供给执行大部分实际工作的“保存”例程。就像,您可以在数据库中存储一行,并将其标记为“未保存”。您对所有行执行此操作,最后调用一个例程来遍历您刚刚存储的所有数据,并在单个事务小批处理过程中将其全部标记为“已保存”。

同时,您的所有其他 SQL 都会“忽略”未“保存”的数据。加入一些时间戳并进行收割进程清理(如果你真的想打扰 - 将死行留在数据库中实际上可能更便宜,具体取决于数量),这些死的“未保存”行,因为这些是“未提交的”交易。

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

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

于 2009-01-05T15:32:05.643 回答
3

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

于 2009-01-05T15:00:30.717 回答
2

去年我看过SimpleORM ,它的轻量级无魔法设计给我留下了深刻的印象。现在似乎有一个版本 3,但我没有任何经验。

于 2009-01-05T13:58:46.877 回答
2

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

这是一个更简单更直观的 ORM 使用。

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

  • 抢。

于 2009-11-11T11:00:37.513 回答
1

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

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

于 2009-01-05T18:51:56.553 回答
1

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

于 2012-07-27T08:46:51.290 回答
0

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

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

于 2009-01-05T14:37:31.650 回答
0

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

扭矩

于 2009-01-05T14:59:03.357 回答
0

当我自己在寻找 Hibernate 的替代品时,我偶然发现了DataNucleus Access Platform,它是一个 Apache2 许可的 ORM。它不仅仅是 ORM,因为它还在 RDBMS 以外的其他数据源(如 LDAP、DB4O 和 XML)中提供数据的持久性和检索。我没有任何使用经验,但看起来很有趣。

于 2009-01-05T23:01:43.273 回答
0

考虑使用类似tox的东西完全打破你的范式。如果您需要 Java 类,您可以将 XML 结果加载到JDOM中。

于 2009-01-05T23:07:43.650 回答