2011-10-03 42 views
14

我坚持实体时使用了EJB3/JPA,我很高兴看到它如何能够管理我的数据库相关的 任务。 我唯一关心的是异常处理。我在保存实体时的示例代码总是出现在这种风格中。 我在网上阅读的大多数教程都带有这种风格,也不考虑异常处理。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。 谢谢

+0

如果你抛出异常,你并不需要抓住它 –

回答

10

异常处理的想法是在发生任何故障的情况下在一个点上执行一些逻辑。 的尝试捕捉将在您需要处理异常的最后一点被使用或者你需要一个异常转换成另一种异常

假设你的应用程序有许多层,即行动,门面,坚持

代表例外 在这种情况下,在Facade上引发的任何异常都可以引发到上述动作层。 在操作中,特定的异常将被捕获并处理,并显示正确的错误消息。

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

    //call to Persist Layer 
} 

转换期一般例外到App例外 说,在持久性你和DBException如SQLException。此异常不应该被发送这样行动或立面层,所以我们捕捉到的特定异常,然后抛出一个新的异常(应用程序的用户定义的异常)

//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 
      } 
    } 
+3

如果持久层是一个EJB,那么你的方法不起作用,因为在方法返回后提交时会发生许多异常。 – Lii

3

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

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

否则,我会建议遵循例外的“经验法则” - 他们应该首先对待你的所有信息,你需要他们采取行动,否则扔他们,让其他人可以处理。 (如果你把它们扔掉,一定要抛出你可能抛出的最具体的异常形式(不是一般的异常))。在使用JPA时处理异常与一般处理Java异常没什么两样。

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

0

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

EJB处理两种类型的异常1)应用程序异常2)系统异常

应用程序异常检查的异常基本上我们正在使用业务验证和业务规则。

系统异常是运行时异常,所以如果任何运行时的excpetion happend ejb容器会干扰并将运行时异常转换为远程异常。

对于前: 在DAO层

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(); 
} 
在如果任何运行时异常happend,EJB容器将干扰和转换成远程异常EJB层

在接口层:

使这样的JPA - > EJB - >接口