9

ここに画像の説明を入力

上記の構造に従っています ( 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>> 

次の質問があります。

  1. DAO ( ) ではなくコントローラー ( ) によって例外がキャッチされ、コントローラーuserService.addUser(user)にバブルアップされるのはなぜですか?com.bilitutor.cct.control.HomeControllersessionFactory.getCurrentSession().save(user);

  2. org.springframework.dao.DataIntegrityViolationExceptionおそらく例外変換を行うアノテーションを使用しているため、取得していることを理解して@Repositoryいます(間違っている場合は修正してください)。その場合、例外をキャッチしたときに、そのエラー コードを見つけるにはどうすればよいですか?

  3. ベスト プラクティスとして、どのレイヤー (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);
    }

}

ダオ:

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);
        }

    }
}
4

3 に答える 3

1

サービス層で例外が発生しています。これはトレースで確認できます

at com.sun.proxy.$Proxy26.addUser(Unknown Source)

@Transactional
public void addUser(User user) {
    userDAO.addUser(user);
}

前の回答によると、トランザクション境界はサービス層にあるため、そこで例外が発生します。

サービス メソッドから適切なビジネス例外 (チェック例外) をキャッチ/スローすることをお勧めします。サービス メソッドにはビジネス ロジックが組み込まれているため、何か問題が発生した場合は、サービス メソッドがスローする例外を通じて外部の世界に適切に伝達する必要があります。例: WeakPasswordException、UserNameExistsException など

ラップされた例外を確認するためのorg.springframework.dao.DataIntegrityViolationExceptiontry 呼び出し についてgetCause()

于 2013-08-07T05:21:15.687 に答える
0

1. UserDAO.addUser() がトランザクション境界であるため、例外がコントローラーでキャッチされていると思います。

2. DataIntegrityViolationExceptionNestedRuntimeExceptionを拡張するため、getMessage、getMostSpecificCause、getRootCause を使用できます。

3.上記の場合、コントローラーで例外をキャッチする必要があります。例外を処理できるレイヤーで例外をキャッチする必要があります。これまでのところ、オブジェクトのリストを取得する DAO メソッドを書いていた場合の例です。私はおそらくDAOで例外をチェックし、空のリストを返し、エラーをログに記録し、例外をスローします。

于 2013-08-07T05:24:12.557 に答える