【问题标题】:Better Exception Handling in JPAJPA 中更好的异常处理
【发布时间】:2011-11-29 17:03:36
【问题描述】:

我在持久化我的实体时使用了 EJB3/JPA,我很高兴它能够管理我的数据库相关 任务。 我唯一关心的是异常处理。我保存实体时的示例代码总是以这种方式出现。 我在网上阅读的大多数教程都是这种风格,也没有考虑异常处理。

@Stateless
public class StudentFacade{
    @PersistenceContext(unitName = "MyDBPU")
    private EntityManager em;

    public void save(Student student) {
        em.persist(student);
    }
}

但我不知道在 EJB 应用程序中处理异常的最佳方式是什么? 处理异常时最好的方法应该是什么?

这是其他人处理异常的方式吗?会话外观上的 try catch 块?

@Stateless
public class StudentFacade{
    @PersistenceContext(unitName = "MyDBPU")
    private EntityManager em;

    public void save(Student student) {
        try {
            em.persist(student);
        } catch(Exception e) {
            //log it or do something
        }
    }
}

还是让方法抛出异常?

public void save(Student student) throws Exception {
    em.persist(student);
}

我不知道我的理解是否正确,因为我还在学习 EJB。 谢谢

【问题讨论】:

  • 如果你抛出异常,你不需要捕获它

标签: java ejb-3.0 jpa-2.0


【解决方案1】:

异常处理的想法是在发生任何故障时在单点执行一些逻辑。 try catch 将在您需要处理异常或需要将异常转换为另一个异常的最后一点使用

假设您的应用有很多层,即 Action、Facade、Persist

委托异常 在这种情况下,任何在 Facade 上抛出的异常都可以被抛出到上面的动作层。 在行动中,特定的异常将被捕获并使用适当的错误消息进行处理。

//This is in Facade Layer
public void save(Student student) throws AppException{
    //exceptions delegated to action layer

    //call to Persist Layer
}

将一般异常转换为应用异常 说持久化你得到和 DBException 像 sqlException。这个异常不应该这样发送到 Action 或 Facade 层,所以我们捕获特定的异常然后抛出一个新的异常(应用程序的用户定义异常)

//This is in Persist Layer
public void save(Student student) throws AppException{
        //converting general exception to AppException and delegating to Facade Layer

        try{
            em.persist(student);//call to DB. This is in Persist Layer
        }catch(Exception e){
            throw new AppException("DB exception", e)
        }
    }

在行动层 您将在行动中捕获您的异常,然后在那里处理异常

  //This is in Action layer
  public void callSave(Student student){
            try{
                //call Facade layer
            }catch(AppException e){
               //Log error and handle
            }
    }

【讨论】:

  • 如果持久层是 EJB,那么你的方法就行不通,因为在方法返回之后提交时会发生许多异常。
【解决方案2】:

如果你想让你的方法抛出从 em.persistance(...) 得到的异常,那么不要用那个 try/catch 块包围那个语句(因为它会捕获那个块中的每个异常)。

解决此问题的方式取决于应用程序,是否已经存在一些遗留代码。如果有遗留代码,我建议您使用相同的方法(即使在某些情况下速度不是最优的)来保持一致性。

否则,我建议遵循异常的“经验法则” - 应该首先处理它们,因为您拥有采取行动所需的所有信息,否则将它们扔掉以便其他人可以处理。 (如果你把它们扔掉,请确保抛出你可以抛出的最具体形式的异常(不是一般的异常))。使用 JPA 处理异常与一般处理 Java 异常没有什么不同。

我希望这是关于异常的足够简单的信息,而不需要开始“宗教对话”。

【讨论】:

    【解决方案3】:

    如果你的组合是 ejb 和 jpa,那么所有 jpa 异常都是运行时异常。

    ejb 处理 2 类异常 1) 应用程序异常 2) 系统异常

    Application Exceptions 检查异常基本上我们都是在使用业务验证和业务规则。

    System Exceptions 是运行时异常,因此如果发生任何运行时异常,ejb 容器会干扰并将运行时异常转换为远程异常。

    例如: 在道层

    public void store(Cargo cargo) {
        entityManager.persist(cargo);
    }
    

    所有 jpa 异常都只是运行时异常。

    在ejb服务层:

    public TrackingId bookNewCargo(UnLocode originUnLocode,
            UnLocode destinationUnLocode,
            Date arrivalDeadline) {
    
        Cargo cargo = new Cargo(trackingId, routeSpecification);
        cargoRepository.store(cargo);
        return cargo.getTrackingId();
    }
    

    在ejb层如果发生运行时异常,ejb容器会干扰并转化为远程异常。

    在接口层:

     public String register() {
    
        try {
             String   trackingId = bookingServiceFacade.bookNewCargo(
                        originUnlocode,
                        destinationUnlocode,
                        arrivalDeadline);
    
    
        } catch (Exception e) {
            throw new RuntimeException("Error parsing date", e); 
        }
    

    所以像这样的 jpa --> ejb --> 接口

    【讨论】:

      猜你喜欢
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-15
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      相关资源
      最近更新 更多