我正在学习使用JAX-RS进行一些 Restful api开发,并且对我的资源类有疑问。

我的理解是,我的资源类应为RequestScoped,
当它是RequestScoped时,我对实体管理器的persist方法的调用将引发TransactionRequiredException。

如果我将资源类更改为无状态,那么一切都很好,并且实体管理器可以继续存在而不会出现任何问题。

我还是JavaEE的新手,想知道为什么会这样,以及@Stateless批注做了什么,以允许持久性上下文正确注入(inject)。
我还想知道JAX-RS资源类是否为无状态而不是RequestScoped是否存在任何问题,因为我所见的大多数教程都包含它们。

我在下面提供了一些示例代码进行说明。

@Path("Things")
//@Stateless //works just fine when em.persist() is called
@RequestScoped //throws transactionrequiredexception when em.persist() is called
public class ThingsResource{

    @PersistenceContext(unitName = "persistenceUnitName")
    EntityManager em;


    public ThingsResource() { }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Response postThing(ThingDTO thing){

        ThingEntity newThing = new ThingEntity(thing);
        em.persist(newThing);
        em.flush();

        return Response.created(new URI("/" + newThing.getId()).build();

    }
}

最佳答案

马蒂亚斯(Matthias)就在现场。

@Stateless带注释的bean是默认情况下提供Container-Managed-Transactions的EJB。默认情况下,如果EJB的客户端不提供新的事务,则CMT将创建一个新的事务。



在jax-rs上最近的java-ee-7 tuturial中,Oracle提供了使用EJB(@Stateless)的示例。



在这种情况下,@ RequestScoped与@Stateless之间的主要区别在于容器可以池化EJB,并避免了可能会在每个请求上构造的bean可能需要的一些昂贵的构造/破坏操作。

10-04 15:30