使用CDI + WS/RS + JPA构建应用程序

Dap*_*eng 5 jpa jax-rs java-ee cdi java-ee-6

@Path(value = "/user")
@Stateless
public class UserService {

    @Inject
    private UserManager manager;

    @Path(value = "/create")
    @GET
    @Produces(value = MediaType.TEXT_PLAIN)
    public String doCreate(@QueryParam(value = "name") String name) {
        manager.createUser(name);

        return "OK";
    }
}
Run Code Online (Sandbox Code Playgroud)

这是用户管理器impl

public class UserManager {

    @PersistenceContext(unitName = "shop")
    private EntityManager em;

    public void createUser(String name) {
        User user = new User();
        user.setName(name);
        // skip some more initializations 
        em.persist(user);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是如果我没有将UserService标记为@Stateless,那么manager字段为null

但如果我标记@Stateless,我可以注入管理器字段,并且应用程序工作,因为我可以将数据保存到数据库中

只是想知道,这背后的原因是什么?

这是连接应用程序的首选方式吗?

好吧,我正在考虑将EntityManager拉出到生产者,以便它可以共享

Pas*_*ent 8

问题是如果我没有将UserService标记为@Stateless,那么manager字段为null

要进行注入,该类必须是一个托管组件,如Enterprise Beans,Servlets,Filters,JSF托管bean等,或者CDI托管bean(这是Java EE 6的新部分,您可以将任何类作为托管bean与CDI).

那么,如果你不把你的JAX-RS端点变成EJB,那么如何启用注入呢?使用Glassfish v3JAX-RS和CDI集成中很好地解释了这一点:

启用CDI托管bean有两种方法:

  1. 由CDI实例化,由泽西岛管理的生命周期.使用 @ManagedBeanJersey范围注释注释并选择性地注释.

  2. 由CDI实例化和管理.使用CDI范围注释进行注释,例如@RequestScoped(@ManagedBean 不需要)

我还建议检查下面的资源.

这是连接应用程序的首选方式吗?

我会说是的.CDI非常好......你不喜欢注射吗?

好吧,我正在考虑将EntityManager提取给生产者,以便可以共享它

什么之间共享?为什么?在这种情况下,您应该使用EntityManager具有作用域为单个事务的生命周期(事务范围的持久性上下文).换句话说,不要共享它(并且不用担心为每个请求打开和关闭它,这不是一个昂贵的操作).

参考

  • JPA 2.0规范
    • 第7.6节"容器管理的持久性上下文"
    • 第7.6.1节"容器管理的事务范围的持久化上下文"
    • 第7.6.2节"容器管理的扩展持久化上下文"

资源