在Play!框架中,@Transactional如何在控制器之外起作用?

3

我尝试使用注解(Guice)在Play!中实现自己的方法拦截器,但似乎这些注解只有在由Guice创建的包含类中才能起作用(参考此处)。这就带来了一个问题:@Transactional在Play!中的Controller类之外如何工作?它本质上是一个方法拦截器,无论包含类如何创建都可以正常工作吗?我也可以在我的模型和服务类中使用它。


不幸的是,@Transactional 只能在控制器操作中使用。对于任何其他方法,您必须手动包装。这个问题可能会有所帮助:https://dev59.com/FY7ea4cB1Zd3GeqPG94V。 - Kris
嗯,这与我所见到的完全相反。如果我调用一个带有@Transaction注释的服务例程,它似乎仍然可以工作。这是否意味着来自控制器任何位置的调用堆栈中的被调用者都可以使用@Transaction进行注释,但是在控制器上下文之外的任何其他被调用者都不能? - Saksham Gupta
如果您在带有@ Transactional注释的控制器中(整个控制器也可能被注释)从内部调用服务方法,则它将起作用。因此,是的,如果您从注释操作之外的不同位置调用相同的服务方法,则它将无法正常工作。在文档https://www.playframework.com/documentation/2.4.x/JavaJPA#Annotating-JPA-actions-with-@Transactional中,他们还提到了仅限操作。这真是太遗憾了:在任意方法中使用事务注释将是一个很好的功能(在Spring框架中没有问题)。 - Kris
实际上,Play!不允许任意方法遵守@Transaction的事实是有道理的。Play!使用Guice,而在Guice中,除非通过injector.getInstance()调用创建包含注释的对象,否则无法调用基于注释的方法拦截器。Play!可以控制控制器对象的初始化,但不能控制任意对象的创建。 - Saksham Gupta
1个回答

3

@Transactional在控制器外不起作用。您唯一的选择是使用JPA.withTransaction

示例:

public Promise<Integer> doWork() {
    return promise(() -> jpaApi.withTransaction(() -> {
        return JPA.em()
            .createNativeQuery("DELETE FROM table WHERE id=1")
            .executeUpdate();
    }), dbExecutionContext);
}

甚至可以不需要额外的执行上下文(在调用线程中执行):
public Promise<Integer> doWork() {
    return jpaApi.withTransaction(() -> {
        return JPA.em()
                .createNativeQuery("DELETE FROM table WHERE id=1")
                .executeUpdate();
    });
}

不要忘记注入play.db.jpa.JPAApi。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接