考虑一下我正在使用的一些代码的简化视图:
@Stateless(...) @Remote(...) @TransactionAttribute(TransactionAttributeType.MANDATORY) public class FirstEjbType { @EJB(...) private SecondEjbType secondEjb; @EJB(...) private ThirdEjbType thirdEjb; public void doSomething() { secondEjb.doSomething(); // WRITES SOMETHING TO THE DATABASE thirdEjb.doSomething(); // CAN'T SEE THAT SOMETHING IN THE DATABASE! }
我已经在类级别设置了TransactionAttribute注释MANDATORY。我理解这意味着doSomething()必须在提供的事务中调用诸如之类的所有方法。在这种情况下,我们正在使用容器管理的事务。
TransactionAttribute
MANDATORY
doSomething()
在TransactionAttribute根本不被用于SecondEjbType或ThirdEjbType…既没有类,也没有方法的水平。我明白这意味着secondEjb.doSomething()并thirdEjb.doSomething()会为双方提供的事务中进行操作firstEjb.doSomething()。
SecondEjbType
ThirdEjbType
secondEjb.doSomething()
thirdEjb.doSomething()
firstEjb.doSomething()
但是,我严重错过了 某些东西 !如代码注释所示,… secondEjb将数据写入数据库,然后thirdEjb读取该数据作为其操作的一部分。由于所有这些都在同一个事务中运行,因此我不希望隔离级别有任何问题。 但是,无论出于何种原因,secondEjb数据库写操作都不可见thirdEjb。
secondEjb
thirdEjb
我一直跟踪到最大,并且显然没有异常,错误或回退问题……后续的读取根本看不到初始写入。我并没有声称自己是交易管理领域的世界上最伟大的专家……我错过了显而易见的事情吗,或者我的概念理解基本上是正确的,而问题可能出在其他地方吗?
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> <persistence-unit name="pu" transaction-type="JTA"> <jta-data-source>jdbc/datasource</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="toplink.cache.shared.default" value="false"/> </properties> </persistence-unit> </persistence>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="pu" transaction-type="JTA">
<jta-data-source>jdbc/datasource</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="toplink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
</persistence>
我从这里的所有答案中学到了很多东西,也无法对别人表示感谢。但是,我认为我的问题使问题陷入泥潭,最好从另一个问题重新开始。
从一个EJB跳到另一个EJB似乎没有任何关系。为了简化问题,我尝试使用完全隔离到一个EJB的测试用例。我进入了该secondEjb.doSomething()方法,该方法将实体保留到数据库中。在该方法的末尾,我添加了一个em.flush(),并尝试通过JPA查询再次检索该实体。
em.flush()
即使我 仍然使用 刚 保留实体的完全相同的方法 ,但对于随后的查询却不可见。我在其他地方做了一些其他研究,看起来这可能只是事务上下文中JPA的正常隔离模式。一个事务启动后,该事务中的其他查询尚无法查看未提交的数据。
如果我对链接的CodeRanch讨论的摘要是正确的,那么请在JPA上“ y”!:)无论哪种方式,我都重构了代码,以完全避免此问题。