EJB3之JPA程序结构,完美的异常处理

首先得用到封装了基本实体操作的EntityManagerHelper类,这在网上到处都是:

public class EntityManagerHelper {

   private static final EntityManagerFactory emf;
    private static final ThreadLocal<EntityManager> threadLocal;
    private static final Logger logger;


    static {
        emf = Persistence.createEntityManagerFactory("EjbTestPU");
        threadLocal = new ThreadLocal<EntityManager>();
        logger = Logger.getLogger("EjbTestPU");
        logger.setLevel(Level.ALL);
    }

    public static EntityManager getEntityManager() {
        EntityManager em = threadLocal.get();
        if (em == null || !em.isOpen()) {
            em = emf.createEntityManager();
            threadLocal.set(em);
        }
        return em;
    }

    public static void closeEntityManager() {
        EntityManager em = threadLocal.get();
        threadLocal.set(null);
        if (em != null && em.isOpen()) {
            em.close();
        }
    }

    public static void beginTransaction() {
        getEntityManager().getTransaction().begin();
    }

    public static void commit() {
        getEntityManager().getTransaction().commit();
    }

    public static void rollback() {
        getEntityManager().getTransaction().rollback();
    }

    public static Query createQuery(String query) {
        return getEntityManager().createQuery(query);
    }
}

然后呢,所有需要或者不需要事务操作的地方都可以这样写:


try {
       EntityManagerHelper.beginTransaction();

       // 这里是自己的数据库操作

       EntityManagerHelper.commit();
       System.out.println("提交成功!");
} catch (Exception e) {
       System.out.println("提交异常:" + e);
       try {
              EntityManagerHelper.rollback();
              System.out.println("回滚成功");
       } catch (Exception ex) {
              System.out.println("回滚异常:" + ex);
       }
} finally {
       EntityManagerHelper.closeEntityManager();
}

其中重点要注意的地方就是 rollback也需要捕获异常。只有捕获了所有异常,程序才不会“飞”掉。

很显然,如果程序中所有实体操作的地方都这样写,不累死才怪呢,所以可以写这样一个抽象类封装异常处理:

public abstract class Transaction {

    final static Logger logger = Logger.getLogger(Transaction.class);

    public abstract void run();

    public void start() {
        EntityManagerHelper EntityManagerHelper = EntityManagerHelper.getInstance();
        try {
            EntityManagerHelper.beginTransaction();
            run();
            EntityManagerHelper.commit();
            logger.info("事务提交成功");
        } catch (Exception e) {
            System.out.println("事务提交异常:" + e);
            try {
                EntityManagerHelper.rollback();
                System.out.println("事务回滚成功");
            } catch (Exception ex) {
                System.out.println("事务回滚异常:" + ex);
            }
        } finally {
            EntityManagerHelper.closeEntityManager();
        }
    }
}

使用的时候只需要继承此抽象类即可,例如:


(new Transaction() {

       @Override
       public void run() {

              // 这里是自己的数据库操作

       }
}).start();

还有一种方法:
在EntityManagerHepler中新建一个方法doTransaction,这样貌似更符合Java的一般习惯:
public void doTransaction(Runnable runnable) {
    try {
        EntityManagerHelper.beginTransaction();
        runnable.run();
        EntityManagerHelper.commit();
        logger.info("事务提交成功");
    } catch (Exception e) {
        logger.error("事务提交异常:" + e);
        try {
            EntityManagerHelper.rollback();
            logger.info("事务回滚成功");
        } catch (Exception ex) {
            logger.error("事务回滚异常:" + ex);
        }
    } finally {
        EntityManagerHelper.closeEntityManager();
    }
}

进一步,Exception可以细化成PersistenceException,这样避免和其它异常相混淆,再加上后来查JavaDoc发现漏掉两个异常,所以这样应该完美了:
public void doTransaction(Runnable runnable) {
    try {
        EntityManagerHelper.beginTransaction();
        runnable.run();
        EntityManagerHelper.commit();
        logger.info("事务执行成功");
    } catch (PersistenceException e) {
        logger.error("持久化异常:" + e);
        try {
            EntityManagerHelper.rollback();
            logger.info("事务回滚成功");
        } catch (Exception ex) {
            logger.error("事务回滚异常:" + ex);
        }
    } catch (IllegalStateException e) {
        logger.error("非法状态异常:" + e);
        try {
            EntityManagerHelper.rollback();
            logger.info("事务回滚成功");
        } catch (Exception ex) {
            logger.error("事务回滚异常:" + ex);
        }
    } catch (IllegalArgumentException e) {
        logger.error("非法参数异常:" + e);
        try {
            EntityManagerHelper.rollback();
            logger.info("事务回滚成功");
        } catch (Exception ex) {
            logger.error("事务回滚异常:" + ex);
        }
    } finally {
        EntityManagerHelper.closeEntityManager();
    }
}

使用的时候有两点需要注意:

1、Runnable中应该避免抛出PersistenceException中包含的两个子异常NonUniqueResultException, NoResultException,解决方法是禁用Query.getSingleResult()方法,取而代之以getResultList()方法 - 这应该是一个好习惯。

2、Runnable如果有异常捕获的结构,注意不要捕获通用的Exception异常,而应该具体异常具体对待,避免“吃掉”JPA的异常 - 这也应该是一个好习惯。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值