理解EJB中的JTA:不刷新

时间:2012-03-21 23:02:26

标签: jpa ejb eclipselink jta

所以我在类级别用@TransactionAttribute(TransactionAttributeType.REQUIRED)注释了这个EJB,所以每个方法都应该在一个事务中执行,除非我重写这个行为,当提交事务时,数据是要刷新的,对吧?到现在为止还挺好。 所以现在我有一个public User find(String email)方法,用@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)注释,所以这个方法不会在事务中执行,因为它只提取数据。

好的,所以我正在测试我的应用程序,我有一个引导程序方法,使用ejb创建几个实体,然后使用find方法获取一个。 在我看来,应该发生什么:

- >我创建了一个在事务中执行的调用save(User u)的实体1。它提交,数据被刷新。

- >使用另外两个实体重复此步骤。他们的事务提交,数据被刷新。

- >此时我的L2缓存(使用Eclipselink)和我的数据库中应该有3个实体。

- >我调用find(String email)方法。它找到一个实体,返回它,没有异常,我的代码执行得很好,我很兴奋,我打开啤酒,我不需要在stackoverflow中提问。

实际发生的事情:

- >我创建了所有3个实体。没有例外。

- >我调用了find(String email)方法,它引发了一个EjbException,因为它找不到实体,调试我发现当调用这个方法时,数据库为空,没有数据被刷新(即使我在明确创建实体时调用了flush方法,但这无论如何都不是必需的)。它抛出了EJbException,我的代码停止了,我再次检查数据库,现在引发了entites,一旦异常被抛出,因为它们不在那里。 如果我从find方法中删除@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED),导致它在事务中执行搜索,我的代码就可以工作。

- >我不开啤酒。

所以现在认真地说,发生了什么?为什么我需要在事务中搜索实体,否则它不会刷新任何东西?

编辑:持久单位:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="TribunalExpedientes" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>tribunalexpedientes</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <shared-cache-mode>ALL</shared-cache-mode>
     <properties>
      <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
     </properties>
  </persistence-unit>
</persistence>

除了在搜索时没有找到任何实体的情况之外,没有引发异常,之后,缓存被刷新到数据库。

3 个答案:

答案 0 :(得分:3)

我的猜测是你没有正确配置。包括您的persistence.xml以及您正在使用的应用程序服务器和数据库。

您使用的是JTA还是RESOURCE_LOCAL,您应该使用JTA,并且应该在persistence.xml中设置目标服务器。

同时检查是否有任何错误。如果发生错误,则将回滚事务。

NOT_SUPPORTED通常不是一个好主意,它意味着如果在事务中调用此方法,则会抛出异常。这可能是正在发生的事情。

答案 1 :(得分:1)

添加将在执行语句时以及事务提交时显示的内容。由于NOT_SUPPORTED暂停了事务,因此只有先前的事务已提交才能“查找”数据。很可能您的保存方法包含在您的find方法暂停的较大事务中。 Flush不会改变这一点,因为这些数据仍然是事务隔离的。

尝试使用REQUIRES_NEW将保存方法放在他们自己的事务中,这些事务在完成后会被提交。

答案 2 :(得分:0)

好吧,提交交易不需要Eclipselink来刷新数据。这就是原因。在我看来,这是一个非常丑陋的行为。 Eclipselink允许在想要执行时刷新数据。我也遇到了一些问题。例如。当使用@PrePersist或@PreUpdate时,无法保证在提交事务时会发生这种情况。例如。在计算某些统计数据时,您无法在同一交易中使用它们,因为Eclipselink可以在交易完成时进行处理。

您必须使用您使用的实体才能制作em.persist()。如果您执行数据库查询。 Eclipselink需要刷新实体,因为查询可能不正确。但是,在尝试扩展应用程序时,使用em.flush()会导致一些非常难看的性能问题。