2016-08-04 68 views
1

私はspring mvcアプリケーションを構築しています。重複(ユーザ名はプライマリキー)エントリを追加して別のユーザ名を選択するように通知する必要があります。spring mvcアプリケーションでデータベースに重複したユーザー名を追加する際に例外を処理する方法

私はユーザー登録オプションを作成中です。すでに存在するユーザー名をユーザーに入力するまではすべて動作します。さて、username列は私のデータベースの主キーなので、それは慎重だった。

私はこれを処理するためのオプションを探しています:

これは、これは私のリポジトリです

create table users(
    username varchar(50) not null primary key, 
    password varchar(50) not null); 

私のSQLテーブルです:

@Repository 

class UserRepositoryImpl implements UserRepository{ 

    @Autowired 
    private JdbcTemplate jdbcTemplate; 


    @Override 
    public void addUser(User user) throws MySQLIntegrityConstraintViolationException { 
     /*language=SQL*/ 
     String SQL_ADD_USER= "INSERT INTO users VALUES (?,?)"; 

     String username = user.getUsername(); 
     String password = user.getPassword(); 
     jdbcTemplate.update(SQL_ADD_USER, username, password); 

    } 
} 

、これは私のコントローラの一部です。クラス:

@RequestMapping(value="/register", method = RequestMethod.GET) 
public String registerPage(@ModelAttribute("user") User user){return "register";} 

@RequestMapping(value="/register", method=RequestMethod.POST) 
public String processRegisterUser(@ModelAttribute("user") User user, BindingResult result){ 

    try { 
     userRepository.addUser(user); 
    } catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException e) { 

     //some line of code that would add information to the view that user with given username already exists. 
    } 


    return "redirect:/login"; 
} 

私は、重複したエントリを追加する際に発生する例外を処理しようとしました。このため、私はこの句をpublic void addUser(ユーザユーザ)にthrows MySQLIntegrityConstraintViolationExceptionと置いています。次のステップでは、この例外をpublic String processRegisterUserメソッドで処理して、指定したユーザー名が占有されていることをユーザーに通知できるようにしたいと考えました。まあ、それは動作しません。私はcom.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationExceptionを扱うことができない、ビュー内の重複エラーの代わりに警告を追加する時に私が取得:

HTTP Status 500 - Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT INTO users VALUES (?,?)]; Duplicate entry 'user' for key 'PRIMARY'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'user' for key 'PRIMARY' 

type Exception report 

message Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT INTO users VALUES (?,?)]; Duplicate entry 'user' for key 'PRIMARY'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'user' for key 'PRIMARY' 

description The server encountered an internal error that prevented it from fulfilling this request. 

exception 

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT INTO users VALUES (?,?)]; Duplicate entry 'user' for key 'PRIMARY'; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'user' for key 'PRIMARY' 
     org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973) 
     org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:650) 
     org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:731) 
     org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
     org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
     org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 
     org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 
     org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
     org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) 
     org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
     org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 

あなたがコメントしてくださいすべての詳細が必要な場合。

+0

登録フォームを表示するjspページがありますか? – lenach87

+0

です。それはうまく動作します。さて、私はまだ登録フォームにエラーメッセージを表示するためにフィールドを追加しませんでした。しかしそれは問題ではありません。私はテストのためのtry-catchブロックにいくつかのリダクションを入れました – Przemek

+0

私はそれが私のために働く方法を教えてくれますが、私の場合、例外ではなくHibernateの検証を使用しました。私の例を聞きたいのですか、あるいは例外部分に固執したいですか? – lenach87

答えて

1

あなたはMySQLIntegrityConstraintViolationExceptionだけを処理しています.NestedServletExceptionとDuplicateKeyExceptionという例外はありません。したがって、stacktraceを取得していてtry/catchが機能していません。

ところで、ユーザー名が既に存在するかどうかを確認するための追加のメソッドを作成していない場合は、エラーメッセージを表示してください。そうでない場合はユーザーを追加してください。

class UserRepositoryImpl implements UserRepository{ 
    //..... 
    public int isUsernameExist(String username){ 
     String sql = "SELECT COUNT(*) FROM users WHERE username=?"; 
     return jdbcTemplate.queryForObject(sql, new Object[] { username }, String.class); 
    } 
    //.... 
} 

@RequestMapping(value="/register", method=RequestMethod.POST) 
public String processRegisterUser(@ModelAttribute("user") User user, BindingResult result){ 
    int status = userRepository.isUserExist(user.getUsername()); 
    if(status==1){ 
     //Username exist... redirect and display error msg. 
    } else { 
     userRepository.addUser(user); 
    } 
    //..... 
} 
+0

これは、ユーザーが存在しているかどうかを確認してください。しかし、それは効率的なソリューションですか?ユーザーが非常に多いfb dtabseにユーザーを登録したいとします。私はproffesionalプログラマーがこの問題をどのように解決するのか興味があります。この問題を解決するには、推奨パターンが必要です。 – Przemek

+0

数百万回のトランザクションの場合、データベースへの呼び出しが2回あるためオーバーヘッドの問題が発生する可能性があります。あなたは、例外で重複するユーザー名エラーを処理したい場合は、MySQLIntegrityConstraintViolationExceptionの代わりにExceptionを使用して、すべての種類の例外を処理できるようにしてください。 –

+0

まあ、私は例外を処理することができます。とにかく。私の問題を例外処理で解決するのは良い習慣ですか?私はいくつかのプロの開発者がこれを解決するだろうと思っています。 – Przemek

1

あなたはDB接続のための春jdbcTemplateを使用していて、このに記載されているように、スプリング例外org.springframework.dao.DuplicateKeyException

+0

DuplicateKeyExceptionを使ってMySQLIntegrityConstraintViolationExceptionをスワップするだけです。私は初心者であり、プロの開発者が私の問題をどのように処理するのか不思議です。私は、同じユーザー名を使用することを許可しないことを意味し、登録時にウェブアプリケーションで再度電子メールを送ります。 – Przemek

1

Query.uniqueResult()を試してキャッチしようとすることができますので、それは、彼自身の例外階層を持っていますarticleまたはelse

public Account getAccountByAccountIdAndType(Long accountId, AccountType accountType) { 

    Account account = null; 
    try { 
     Query query = getSession().getNamedQuery("getAccountByAccountId"); 
     query.setLong("accountId", accountId); 
     query.setString("accountType", AccountType.SAVING.toString()); 
     Account account = (Account)Query.uniqueResult(); 
    } catch(NonUniqueResultException) { 
     throw new RuntimeException("Two account found with same account number and type : Acc No-" + accountId); 
    } 
    if (account == null) { 
     throw new RuntimeException("Unable to find Account for account number :" + accountId); 
    } 
    return account; 
} 

Entityクラス

@NamedQuery(
name = "getAccountByAccountId", 
query = "from Account where username = :username") 
@Entity 
@Table(name = "account") 
public class Account { 
関連する問題