Jakarta ee 在数据库事务中使用什么注释包装方法
我有一个持久化数据的web服务,其中一个方法需要在数据库事务中。实质上,它看起来是这样的: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 " +
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" ...>