JPA数据访问对象 - 异常处理和回滚 [英] JPA data access object - exception handling and rollback

查看:224
本文介绍了JPA数据访问对象 - 异常处理和回滚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道数据访问对象中最好的异常处理方式是什么,我对生产质量代码感兴趣。

I'd like to know what the best way of exception handling in data access objects is, I'm interested in production quality code.

作为示例

public UserDaoImpl implements UserDao{
    @PersistenceContext
    private EntityManager em;

    void save(User user){
       em.persist(user);
    }
    User getById(long id){
       return em.find(User.class,id);
    }
}

比方说我在某个地方有一个RegisterService在某些时候我想将用户保存到数据库中。并且每个用户都需要有一个唯一的电子邮件。
如何检查此代码以及代码的位置?
在持久化之前,我们是否使用查询检查保存方法中是否有用户已使用该电子邮件?或者该代码是否转到服务中?或者我们可能会尝试捕捉一些例外情况?

Let's say that for example I have a RegisterService somewhere where at some point I'd like to save the user to the database. And that each User needs to have a unique email. How do you check that and where does this code go ? Do we check if there's a user with that email already in the save method using queries before persisting? Or does that code go to the service? Or maybe we try to catch some exceptions?

但据我所知,除了确定发生了什么外,我们可能会尝试捕获一个ConstraintViolationException,但这并没有明确告诉我们发生了什么。

But with exceptions as far as I know we'd never know for sure what happened, we could try to catch a ConstraintViolationException but that doesn't tell us explicitely what happened.

它在生产质量代码中看起来如何?

How does it look in a production quality code?

推荐答案


让我们说,例如我在某个地方有一个RegisterService,在某些时候我想将用户保存到数据库中。并且每个用户都需要有一个唯一的电子邮件。你如何检查这个代码到底在哪里?

在你插入的同一个交易中检查它并抛出一个触发完全回滚的自定义异常。

Check it in the same transaction as you're inserting and throw a custom exception which triggers a full rollback.

签入同一事务将保证DB在插入过程中不会导致约束违规异常。建议你的DAO实际上是一个 @Stateless EJB(基于你用[java-ee]而不是例如[spring]标记你的问题的事实),然后客户端的每个单个方法调用默认计为单个事务。

Checking in the same transaction will guarantee that the DB won't cause a constraint violation exception during the insert. Proposed that your "DAO" is actually a @Stateless EJB (based on the fact that you tagged your question with [java-ee] and not e.g. [spring]), then each single method call by the client counts by default as a single transaction.

抛出自定义服务层特定异常会分离您的前端(即调用该业务服务方法的任何人,例如JSF,JAX-RS,Spring MVC,JSP / Servlet等) )来自底层持久层。换句话说,您的前端代码库完全没有 javax.persistence。* imports / dependencies。建议您使用EJB作为服务层API,然后使用 @ApplicationException(rollback = true)

Throwing a custom service layer specific exception decouples your frontend (i.e. whoever is calling that business service method, e.g. JSF, JAX-RS, Spring MVC, JSP/Servlet, etc) from the underlying persistence layer. In other words, your frontend codebase is completely free of javax.persistence.* imports/dependencies. Proposed that you're using EJB as service layer API, then annotate the custom exception with @ApplicationException(rollback=true).

例如

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public User findByEmail(String email) {
        List<User> users = em.createQuery("SELECT u FROM User u WHERE email = :email", User.class)
            .setParameter("email", email)
            .getResultList();
        return users.isEmpty() ? null : users.get(0);
    }

    public void register(User user) {
        if (findByEmail(user.getEmail()) != null) {
            throw new DuplicateEntityException();
        }

        em.persist(user);
    }

    // ...
}





@ApplicationException(rollback=true)
public class DuplicateEntityException extends RuntimeException {}

然后,在您的前端,只捕获自定义服务层特定的异常(我们现在知道它确实是导致异常的预期意外情况)并处理因此,例如显示嘿,你已经注册了!也许你想登录或重置你的密码?给最终用户的消息。

Then, in your frontend, just catch that custom service layer specific exception (which we now know for sure that it's exactly the expected unexpected condition causing the exception) and handle accordingly by e.g. showing a "Hey, you're already registered! Perhaps you want to login or reset your password?" message to enduser.

  • Letting the presentation layer (JSF) handle business exceptions from service layer (EJB)
  • JSF Controller, Service and DAO

这篇关于JPA数据访问对象 - 异常处理和回滚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆