Jpa 理解EJB中的JTA:不刷新
因此,我用Jpa 理解EJB中的JTA:不刷新,jpa,ejb,eclipselink,jta,Jpa,Ejb,Eclipselink,Jta,因此,我用@TransactionAttribute(TransactionAttributeType.REQUIRED)在类级别对这个EJB进行注释,这样每个方法都应该在事务中执行,除非我重写这个行为,当事务被提交时,数据应该被刷新,对吗?到现在为止,一直都还不错。 所以现在我有了一个公共用户查找(字符串电子邮件)方法,用@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)注释,所以这个方法不会在事务中执行,因为它只获取数据
@TransactionAttribute(TransactionAttributeType.REQUIRED)
在类级别对这个EJB进行注释,这样每个方法都应该在事务中执行,除非我重写这个行为,当事务被提交时,数据应该被刷新,对吗?到现在为止,一直都还不错。
所以现在我有了一个公共用户查找(字符串电子邮件)
方法,用@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
注释,所以这个方法不会在事务中执行,因为它只获取数据
好的,我正在测试我的应用程序,我有一个booter方法,它使用ejb创建两个实体,然后使用find方法获取一个实体。
在我看来,应该发生什么:
->我创建实体1,调用在事务中执行的save(User u)
。它提交时,数据被刷新
->对另外两个实体重复此步骤。当事务提交时,数据被刷新
->此时,我的二级缓存(使用Eclipselink)和数据库中应该有3个实体
->我调用find(字符串电子邮件)
方法。它找到一个实体,返回它,没有异常,我的代码执行得很好,我很兴奋,我打开一瓶啤酒,我不需要在stackoverflow中问任何问题
实际发生的情况:
->我创建了所有3个实体。也不例外
->我调用find(String email)
方法,它会引发一个EjbException,因为它找不到实体,调试时我发现当调用这个方法时,数据库是空的,没有数据被刷新(即使我在显式创建实体时调用flush方法,这无论如何都不必要)。它抛出了EJbException,我的代码停止了,我再次检查了数据库,现在实体就在那里,因为它们不在那里而抛出了异常。
如果我从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>
org.eclipse.persistence.jpa.PersistenceProvider
贡品
假的
全部的
除了在搜索时没有找到实体之外,没有引发任何异常,在此之后,缓存将刷新到数据库。我猜您没有正确配置内容。包括persistence.xml以及正在使用的应用程序服务器和数据库 如果您使用的是JTA或RESOURCE_LOCAL,那么您应该使用JTA,并且应该在persistence.xml中设置目标服务器 还要检查是否有任何错误。如果发生错误,则事务将回滚
不支持通常不是一个好主意,这意味着如果在事务中调用此方法,将引发异常。这可能就是正在发生的情况。添加它,它将显示何时执行语句以及何时提交事务。由于不支持挂起事务,因此只有在先前的事务已提交的情况下才能“查找”数据。很可能您的save方法被包装在一个更大的事务中,而find方法正在挂起该事务。Flush不会更改此项,因为此数据仍处于事务隔离状态
尝试使用REQUIRES_NEW将保存方法放入它们自己的事务中,在完成时提交。好的,提交事务不需要Eclipselink刷新数据。这就是原因。我认为这是一种非常丑陋的行为。Eclipselink可以在需要时刷新数据。我也有一些问题。例如,当使用@PrePersist或@PreUpdate时,不保证在提交事务时发生这种情况。例如,在计算某些统计数据时,您不能在同一事务中使用它们,因为Eclipselink可以在事务已经完成时进行处理
必须使用所使用的实体才能使em.persist()持久化。以防执行数据库查询。刷新实体需要Eclipselink,因为查询可能不正确。但是在尝试扩展应用程序时,使用em.flush()会导致一些非常糟糕的性能问题。这是“从不”属性,不受支持会挂起事务(如果处于活动状态),或者如果未处于活动状态,则会在事务外执行该方法。它使方法成为非事务性的。如果在事务中调用该方法,则不会引发异常。那么,如果使用“从不”,是否会收到异常?@Chris我收到异常是!它说:
javax.ejb.EJBException:ejb不能在全局事务中调用
,您是对的,事务没有提交,而是启动了“全局”事务。为什么?这是某种优化吗?我从一个请求范围的CDIBean调用,该bean是非事务性的。我不知道发生了什么事