典型的 EJB3/JPA/JSF 中的事务范围是什么?

Mig*_*ing 5 java architecture jsf transactions ejb-3.0

假设您有一个带有 EJB3/JPA 和 JSF 堆栈的 Web 应用程序。AFAIK 您可以使用不同的托管 bean 设计您的屏幕,例如,假设 aHeaderBean和 a ListingBean。由于 EJB3 AFAIK 中没有 OSIF 模式,因此在以下伪代码中执行了多少不同的事务:

@ManagedBean
class HeaderBean {
  @PreConstruct
  load(){
    // enters transaction boundary, probably will create a new tx
    headerInfo = ejb.loadFromDb();
  }
}

@ManagedBean
class ListingBean{
  @PreConstruct()
  list(){
    // enters transaction boundary, probably will NOT join the headerBean tx
    List<Data> listing = eao.loadFromDb(0, 20);
  }
}
Run Code Online (Sandbox Code Playgroud)

AFAIK 当您离开EJB层时,所有事务都已提交;因此,如果我从表示层调用两个不同的SLSB,它将在两个不同的事务中运行(并且可能会破坏我的ACID期望,对吗?)。


说明:我知道 EJB3 事务行为,例如required, never, requires_new等等。我的问题更多是关于如何View-First(例如 JSF)促进这种屏幕数据可能跨越多个事务的设计,因此可能不准确。

我更喜欢更长的交易但正确的数据,而不是短的交易但不正确的数据。我想知道像 jBoss Seam 这样的新框架是否会以某种方式促进这一点或提供替代设计(例如:Open-Session-In-View 模式)。

djn*_*jna 2

有一些选项可以控制 EJB 的事务行为。通常它们有一个“需要事务”设置,这样,如果在事务已到位的情况下调用 bean,则该 bean 的工作将包含在已建立的事务中,否则事务将在 bean 返回时启动并完成。

在您的代码中,在进入 EJB 时没有任何事务,因此正如您所说,从 EJB 返回时任何事务都已解决。

尽管这似乎存在潜在问题,因为您可能会获得不一致的数据视图,但我认为这种行为是可取的。我们希望事务花费的时间很短——否则数据库锁会被长时间持有,从而导致并发性受到影响。

EJB层应该被视为提供原子服务并相应地设计和使用。我不知道我是否正确地阅读了您的代码,但是为标题和正文设置单独的访问方法可能不是最好的设计。如果您需要标头和正文之间的一致性,那么在一次调用中获取所有数据可能更好,并且实际上在单个数据库交互中更有效地完成。

--补充--- 您已在问题中澄清,您确实关心屏幕不同部分之间的一致性,如果使用简单的 JSF 技术进行编码,将使用单独的事务。

我认为,当这种不一致极不可能或不可避免时,默认的 JSF 方法是合适的。例子: 1). 不太可能:查询历史数据、昨天的交易总额和昨天的交易列表。在历史记录无法更改的系统中,此类单独的查询将是一致的。2)。不可避免:摘要来自一个系统,明细来自不同系统,两个系统之间没有事务协调,无法保证一致性。我们只需向用户表明这两个视图可能略有不一致。

如果您真正想要一致性,请使用不同的方法,在单个请求中获取所有数据并保存它(例如在会话或请求中),然后在两个视图中使用它 - 如果您关心这些事情,视图不应该获取自己的数据。

我认为您会发现尝试使用事务来保持事物的一致性会增加相当大的复杂性并影响吞吐量。跨视图协调事务的问题是没有简单的“所有者”,如果您重构页面,则需要更改逻辑