迁移EJB 2 CMP实体Bean至EJB 3 JPA时如何处理FinderException?
我刚好处理过类似的EJB2到JPA的迁移场景,给你几个实用的方案来保留原myMethod中的业务逻辑:
1. 直接使用JPA原生的NoResultException
这是最贴合原FinderException语义的替代方案——当JPA查询(不管是JPQL、Criteria API还是Spring Data JPA的查询方法)没有找到匹配结果时,默认会抛出javax.persistence.NoResultException。你只需要把catch块中的FinderException替换成这个异常即可,原有业务逻辑可以完全保留:
public void myMethod(){ ... try { // 假设现在用JPA方式查询,比如EntityManager或Spring Data JPA的repository File file = fileRepository.findFile(inFile); } catch (NoResultException e) { // 原有的业务逻辑完全不动 } }
注意:如果原findFile方法可能因为匹配多个结果抛出FinderException,JPA中对应的情况会抛出NonUniqueResultException。你可以根据原逻辑需求,选择单独捕获这个异常,或者合并捕获两个异常:
catch (NoResultException | NonUniqueResultException e) { // 统一处理找不到或找到多个的情况,和原FinderException逻辑对齐 }
2. 自定义异常兼容原有代码结构
如果你的项目需要保持原有异常体系的一致性,或者想让异常语义更贴近原FinderException,可以自定义一个CustomFinderException,然后在JPA查询的地方捕获原生异常并包装成自定义异常抛出:
首先定义自定义异常:
public class CustomFinderException extends Exception { public CustomFinderException(String message, Throwable cause) { super(message, cause); } }
然后在查询方法中包装异常:
public File findFile(String inFile) throws CustomFinderException { try { return entityManager.createQuery("SELECT f FROM File f WHERE f.name = :name", File.class) .setParameter("name", inFile) .getSingleResult(); } catch (NoResultException | NonUniqueResultException e) { throw new CustomFinderException("File not found or duplicate entries", e); } }
这样原myMethod的catch块只需要替换异常类型即可,业务逻辑完全不变:
catch (CustomFinderException e) { // 原有的业务逻辑保留 }
3. 可选:返回null而非抛出异常(不推荐保留原逻辑)
如果你的团队倾向于避免用异常控制流程,可以修改JPA查询方法返回Optional<File>或直接返回null,然后在myMethod中判断结果是否为空来执行原有逻辑。不过这种方式需要修改原方法结构,如果你想完全保留原catch块的逻辑,这个方案就不太适合。
比如用Optional的方式:
public void myMethod(){ ... Optional<File> fileOpt = fileRepository.findFile(inFile); if (fileOpt.isEmpty()) { // 原catch块中的业务逻辑移到这里 } else { File file = fileOpt.get(); // 原try块中的逻辑 } }
总结来说,方案1是改动最小、最贴合原场景的选择,几乎不需要调整原有业务逻辑,直接替换异常类型即可。
内容的提问来源于stack exchange,提问作者user771221

