Jakarta ee 在数据库事务中使用什么注释包装方法

Jakarta ee 在数据库事务中使用什么注释包装方法,jakarta-ee,transactions,wildfly,java-ee-7,Jakarta Ee,Transactions,Wildfly,Java Ee 7,我有一个持久化数据的web服务,其中一个方法需要在数据库事务中。实质上,它看起来是这样的: public abstract class ControllerBase { //this is a method that needs to run in a transaction void batchUpsert(/* ... */) { try { sql.query("BEGIN").execute(); sql.query("LOCK TABLE " +

我有一个持久化数据的web服务,其中一个方法需要在数据库事务中。实质上,它看起来是这样的:

public abstract class ControllerBase {
  //this is a method that needs to run in a transaction
  void batchUpsert(/* ... */) {
    try {
      sql.query("BEGIN").execute();
      sql.query("LOCK TABLE " + tableName + " IN EXCLUSIVE MODE").execute();
      //do some stuff
    } finally {
      sql.query("COMMIT").execute();
    }
  }
}
web服务在子类中定义并调用上述方法:

@Path("symbology")
@Stateless
public class SymbologyController extends ControllerBase {
  @PUT
  @Path("upsert_symbology")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response upsertSymbology(List<SymbologyRecord> symbology) {
    batchUpsert(SYMBOLOGY, symbology, SYMBOLOGY.SHORT_NAME);
    return Response.ok().build();
  }
}
但是容器(wildfly)似乎没有创建事务,我得到一个例外:

错误:锁表只能在事务块中使用

我还尝试了
@TransactionAttribute
注释,但也不起作用

我应该如何让wildfly知道它需要将我的方法包装到数据库事务中?


编辑

我刚刚意识到交易状态为活动状态:

@Resource TransactionSynchronizationRegistry tsr;


@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
void batchUpsert(/* ... */) {
  LOG.info("Transaction active? {}", tsr.getTransactionStatus() == Status.STATUS_ACTIVE);
  //...
}

输出为true。这不是应该在数据库级别运行与
BEGIN
语句等效的语句吗?

我通常将数据库逻辑划分为不同的外观

@Stateless
public void DBFacade{

  @TransactionAttribute(REQUIRES_NEW(
  public void doSomethingIntransaction(){}
}

@Stateless
@Path("/path")
public class MyFrontendService{
  @EJB
  private DBFacade dbFacade;

  @PUT
  @Path("upsert_symbology")
  @Consumes(MediaType.APPLICATION_JSON)
  public void updateUserData(){
    dbFacade.doSomething();
  }

}
你为什么一定要这样做?
因为如果您不这样做,容器将无法拦截
batchUsert()
的调用,因为您直接调用该方法。但是,如果您使用ejb注入,则注入的实例是实际bean的代理,当您在代理上调用方法时,它们会拦截它,决定它是否需要活动事务,然后调用它所引用的实际方法。这是唯一的ejb方式。您必须委托实际调用。

检查您的数据源是否在wildfly中声明为启用了JTA:

<datasource jta="true" jndi-name="java:jboss/jdbc/ws" ...>


什么是
sql
?它可能未注册到当前事务中。您是否考虑过改用JTA管理的
EntityManager
?@Benjamin我使用的是JOOQ,而
sql
本质上是
数据源
的薄包装器。连接由
@Resource(lookup=“java:jboss/jdbc/ws”)private javax.sql.DataSource postgres提供。我从未使用过JTA,所以不确定它带来了什么。有没有办法将数据源注册到当前事务中?JTA带来了事务管理,
TransactionSynchronizationRegistry
是JTA的一部分。如果您的数据源在wildfly:
中声明启用了JTA,那么它应该可以工作。否则我不知道你使用的这个JOOQ包装器执行什么。。。您可以尝试直接使用数据源?@Benjamin这就是问题所在:数据源上未启用jta(不确定原因)。请随意发表您的评论作为回答。我的代码按原样工作-问题是数据源上没有启用jta。
<datasource jta="true" jndi-name="java:jboss/jdbc/ws" ...>