Ama*_*rsh 8 hibernate exception-handling spring-mvc

我遵循上面建议的结构(http://viralpatel.net/blogs/spring3-mvc-hibernate-maven-tutorial-eclipse-example/).我尝试添加重复条目,这导致以下异常:
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/cct] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: Duplicate entry 'a@b.com' for key 'PRIMARY'; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Duplicate entry 'a@b.com' for key 'PRIMARY'] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'a@b.com' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at << removed for readability>> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at com.sun.proxy.$Proxy26.addUser(Unknown Source)
    at com.bilitutor.cct.control.HomeController.signup(HomeController.java:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    << removed for readability>> 
我有以下问题:
为什么控制器(userService.addUser(user)in com.bilitutor.cct.control.HomeController)捕获异常而不是DAO(sessionFactory.getCurrentSession().save(user);)然后冒泡到控制器?
我明白我得到的是org.springframework.dao.DataIntegrityViolationException因为我正在使用@Repository注释,这可能会进行异常翻译(如果我错了,请纠正我).在这种情况下,当我捕获异常时,如何找到它的错误代码?
作为最佳实践,在哪个层(DAO,服务或控制器)是捕获异常的最佳位置?
相关课程:
控制器:
package com.bilitutor.cct.control;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.web.bind.annotation.ModelAttribute;
import com.bilitutor.cct.bean.*;
import com.bilitutor.cct.service.*;
/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    @Autowired
    UserService userService;
    @ModelAttribute("user")
    public User getUserObect() {
      return new User();
    }
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    /**
     * Landing page. Just return the login.jsp
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Model model) {
        logger.info("home() called");
        return "login";
    }
    /**
     * Login. Either forward to the user's homepage or return back the error
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(Model model) {
        logger.info("login() called");
        return "login";
    }
    /**
     * New User signup. If user already exists, send back the error, or send an email and forward to the email validation page
     */
    @RequestMapping(value = "/signup", method = RequestMethod.POST)
    public String signup(@ModelAttribute("user")User user, BindingResult result) {
        logger.info("signup() : email="+user.getEmail()+" pass="+user.getPassword()+" accessCode="+user.getAccessCode());
        userService.addUser(user);
        return "login";
    }
}
服务:
package com.bilitutor.cct.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.bilitutor.cct.dao.UserDAO;
import com.bilitutor.cct.bean.User;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO;
    @Transactional
    public void addUser(User user) {
        userDAO.addUser(user);
    }
    @Transactional
    public void removeUser(String email) {
        userDAO.removeUser(email);
    }
}
DAO:
package com.bilitutor.cct.dao;
import com.bilitutor.cct.bean.User;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserDAOImpl implements UserDAO {
    @Autowired
    private SessionFactory sessionFactory;
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    public void addUser(User user) {
        sessionFactory.getCurrentSession().save(user);
    }
    public void removeUser(String email) {
        User user = (User) sessionFactory.getCurrentSession().load(User.class, email);
        if (user!=null) {
            sessionFactory.getCurrentSession().delete(user);
        }
    }
}
1.
我怀疑您将控制器处理程序方法作为事务边界,例如如下所示:
@RequestMapping
@Transactional
public String myHandler(..) {
  ...
}
只有在更新同步到数据库后才能检测到重复行,如果您使用 hibernate/jpa,这通常会在事务关闭时发生,因此您会看到它好像来自您的控制器
回想一下,它@Transactional是通过 jdk 代理/方面编织来工作的。
3.
答案取决于您的业务需求。当发生特定异常时,您需要采取什么措施?
| 归档时间: | 
 | 
| 查看次数: | 8733 次 | 
| 最近记录: |