我正在学习使用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可能需要的一些昂贵的构造/破坏操作。