我正在构建spring mvc应用程序。我想不赞成添加重复(用户名是主键)条目,并在视图中通知选择另一个用户名。
我正在处理注册用户选项。一切正常,直到我把用户名已经存在。好吧,这是故意的,因为用户名列是我数据库中的主键。
我正在寻找一个处理这个的选项:
这是我的SQL表
create table users(
username varchar(50) not null primary key,
password varchar(50) not null);
这是我的存储库:
@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);
}
}
这是我的Controller类的一部分:
@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";
}
如您所见,我尝试处理在添加重复条目期间发生的异常。这就是我将此子句throws MySQLIntegrityConstraintViolationException
放在public void addUser(User user)中的原因。在下一步中,我想在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 :(得分:1)
您只处理MySQLIntegrityConstraintViolationException,而不是其他异常:NestedServletException和DuplicateKeyException,因此您将获得stacktrace并且您的try / catch无法正常工作。
BTW,为什么不简单地创建一个额外的方法来检查用户名是否已经存在,如果是,则显示错误消息,否则添加用户。
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);
}
//.....
}
答案 1 :(得分:1)
您正在使用spring jdbcTemplate进行数据库连接,并且它有自己的异常层次结构,因此您可以尝试捕获spring异常org.springframework.dao.DuplicateKeyException
答案 2 :(得分:1)
Query.uniqueResult()
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;
}
实体类
@NamedQuery(
name = "getAccountByAccountId",
query = "from Account where username = :username")
@Entity
@Table(name = "account")
public class Account {
答案 3 :(得分:0)
我将通过捕获异常来解决该问题(以避免竞争条件),然后将一个错误添加到BindingResult中,以便能够在(JSP / Thymeleaf)视图模板中显示该错误。
@Controller
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
/**
* Adds new a user and redirect to users if there are no errors otherwise return add user template.
*/
@PostMapping("/admin/add_user")
public String postUser(Model model, @Valid UserForm userForm, BindingResult result) {
if (result.hasErrors()) {
// Maybe add attributes to the model here. Do not redirect when there are errors.
return "add_user";
}
try {
userService.createUser(
User.withUsername(userForm.getUsername()).password(userForm.getPassword()).roles("ADMIN").build());
} catch (final DuplicateKeyException e) {
result.rejectValue("username", "usernameInUse", "Username is already in use");
return postUser(model, userForm, result);
}
// Redirect after post if there are no errors
return "redirect:/admin/users";
}
}
用户表单包含标准的jsr 303验证批注。
@Data
public class UserForm {
@Length(min = 1, max = 50)
@NotEmpty
private String username;
@NotEmpty
private String password;
}