我有一个中等规模的 Java EE 6 项目,它使用多个 EJB,其中一个唯一目的是通过 JPA 管理数据库调用。我的问题是添加一个执行一些随机功能的新类,然后调用数据库访问 EJB 以保留此类中的数据的最佳方法是什么。

如果这个新类需要访问注释和注入(inject),它是否必须是 EJB?如果它必须与项目的其余部分一起部署,它是否必须是 EJB?

有人告诉我,如果您想向项目添加新的逻辑类,它要么必须是 EJB,要么您可以使用 JNDI 远程集成它以访问 EJB 元素并创建某种客户端界面。现在我的新类只是一个 POJO,但它无法访问 EJB 功能。

我一般应该怎么做?

编辑:请注意我的问题不是关于数据库访问。这只是我正在使用的一个例子。我的客人更广泛。我想知道如何从我创建的其他类访问 EJB 方法。从一个 EJB 到另一个 EJB,您可以简单地注入(inject)另一个 EJB,因为它们都是容器管理的。但是假设我在与 EJB 相同的包中创建了另一个类,我该如何访问这些方法?有可能吗?这里的最佳实践是什么。

现在我有一个类从 URL 获取 twitter 提要数据,然后解析 JSON 并返回前 10 个条目的字符串。我想调用管理数据库访问的 EJB 并将该字符串传递给其相应的方法,但我不能这样做,因为我的类也不是 EJB。

最佳答案

EJB 通常用于实现任何类型的服务。它们与 JPA 集成得非常好,因此通常用于数据库访问,但这不是它们唯一的用途。

EJB 通常是 而不是 适合的是建模数据。 IE。它们应该是你申请中的动词,而不是名词。因此,以下是 错误的 :

@Stateless
@Entity
public class CreditCard { // silly, don't do this!

     @Id
     Long id; + getters/setters
     Data expiration date; + getters/setters
}

以下更好,它是一项服务,当您的应用程序启动时从某处获取一些报价数据:
@Singleton
@Startup
public class QuoteFetcher {

     private List<Quote> quotes; // + getter

     @PostConstruct
     public fetchQuote()
          quotes = SomeUrlBuilder.someUrl().getQuotes();
     }
 }

以下是强制性 DAO 示例:
@Stateless
public class JPAInvoiceDAO implements InvoiceDAO {

     @PersistenceContext
     private EntityManager entityManager;

     public Invoice getById(Long invoiceId) {
           return entityManager.find(invoiceId, Invoice.class);
     }

     // More DAO methods
}

下面显示了如何使用声明性安全性,以及 bean 如何查找已从外部映射到其私有(private)上下文 (ENC) 的内容:
@Stateless
public class TokenFetcher

    @Resource
    private SessionContext sessionContext;

    @RolesAllowed("SYSTEM")
    public Token getToken() {
        return (Token) sessionContext.lookup("token");
    }
}

问题的第二部分似乎是如何在代码中使用这些 bean。基本上有四种方法:
  • 在托管 bean 中注入(inject)
  • 通过 JNDI 引导
  • 启动时自动调用
  • 通过计时器自动

  • 注入(inject)是最简单的方法,但只有托管 bean 是注入(inject)候选者(基本上意味着 Java EE 框架创建 bean,并且您不使用 new() 来实例化它)。

    例如。注入(inject):
    @ManagedBean
    public class InvoiceBacking {
    
         private Long invoiceId; // + getter/setter
         private Invoice invoice; // + getter
    
         @EJB
         private InvoiceDAO invoiceDAO;
    
         @PostConstruct
         public void init() {
              invoice = invoiceDAO.getById(invoiceId);
         }
     }
    

    (另见 Communication in JSF 2.0#Processing GET request parameters )

    通过 JNDI 引导:
     public class SomeQuartzJob implements Job {
    
         public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
              InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
              List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
              // verbose exception handling and closing JNDI context omitted for brevity
         }
      }
    

    前面展示的@Singleton bean 是 Java EE 框架如何在启动时调用您的代码本身的示例。对于自动计时器,您将在 bean 的方法上使用 @Schedule 注释。

    关于java - 在 Java EE 中与 EJB 交互的最佳方式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8453317/

    10-12 00:12
    查看更多