業務チェック処理を実装
リクエストパラメータの単項目/関連項目バリデーションとは別に業務的なチェック処理を追加して、エラーメッセージを返却するところまでを追加する
/src/main/java/com/example/demo/domain/mapper/UsersMapper.java
- メールアドレスが重複するレコードが登録されているか検索するメソッドを追加
Users lockByMailAddress(@Param("mailAddress") String mailAddress);
/src/main/resources/com/example/demo/domain/mapper/UsersMapper.xml
- メールアドレスが重複するレコードが登録されているか検索するSQLを追加
<select id="lockByMailAddress" resultType="com.example.demo.domain.model.Users"> SELECT ID, MAIL_ADDRESS, USER_NAME, PASSWORD, LAST_LOGIN_TIME, REGIST_TIME, UPDATE_TIME, DELETED FROM t_users WHERE MAIL_ADDRESS = #{mailAddress} AND DELETED = 0 FOR UPDATE </select>
/src/main/java/com/example/demo/domain/repository/UsersRepository.java
- メールアドレスが重複するレコードが登録されているか検索するメソッドを追加
public Users lockByMailAddress(String mailAddress) { return usersMapper.lockByMailAddress(mailAddress); }
/src/main/java/com/example/demo/service/UsersService.java
- メールアドレスが重複するレコードが存在した場合は処理を中断し、業務例外をthrow
@Transactional(readOnly = false) public UserDto create(UserDto dto) { Users duplicated = usersRepository.lockByMailAddress(dto.getMailAddress()); if (duplicated != null) { throw new BusinessException("errors.users.mailAddress.duplicated", dto.getMailAddress()); } final Users users = Users.builder() .mailAddress(dto.getMailAddress()) .userName(dto.getUserName()) .password(dto.getPassword()) .registTime(DateUtils.getThreadDateTime()) .updateTime(DateUtils.getThreadDateTime()) .deleted(0) .build(); usersRepository.create(users); LOGGER.info("#users : {}", users); return convert(users); }
/src/main/java/com/example/demo/common/utils/SystemException.java
package com.example.demo.common.utils; import lombok.Getter; @Getter public class SystemException extends RuntimeException { /** * SerialVersionUID. */ private static final long serialVersionUID = -8269072520808618210L; private String code; private Exception nested; public SystemException(String code, Exception nested) { super(); this.code = code; this.nested = nested; } public SystemException(String code) { super(); this.code = code; } }
/src/main/java/com/example/demo/common/utils/BusinessException.java
package com.example.demo.common.utils; import java.util.List; import com.google.common.collect.Lists; import lombok.AllArgsConstructor; import lombok.Getter; @Getter public class BusinessException extends RuntimeException { /** * SerialVersionUID. */ private static final long serialVersionUID = -2911618850319099751L; private List<ErrorInfo> errors = Lists.newArrayList(); public BusinessException(String code) { this(code, new Object[0]); } public BusinessException(String code, Object... params) { super(); final ErrorInfo error = new ErrorInfo(code, params); errors.add(error); } @Getter @AllArgsConstructor public static class ErrorInfo { private String code; private Object[] params = new Object[0]; } }
/src/main/java/com/example/demo/web/controller/ExceptionController.java
@ExceptionHandler(BusinessException.class) public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) { final List<ErrorResponse.Error> errors = Lists.newArrayList(); final List<ErrorInfo> errorInfoList = e.getErrors(); for (ErrorInfo errorInfo : errorInfoList) { errors.add(new ErrorResponse.Error(null, messageSource.getMessage(errorInfo.getCode(), errorInfo.getParams(), Locale.getDefault()))); } return new ResponseEntity<>(new ErrorResponse(errors), HttpStatus.BAD_REQUEST); } @ExceptionHandler(SystemException.class) public ResponseEntity<ErrorResponse> handleSystemException(SystemException e) { String errMessage = "system error happend."; if (e.getCode() != null) { errMessage = messageSource.getMessage(e.getCode(), new Object[0], Locale.getDefault()); } LOGGER.error(errMessage, e); ErrorResponse.Error error = new ErrorResponse.Error(null, errMessage); return new ResponseEntity<>(new ErrorResponse(error), HttpStatus.INTERNAL_SERVER_ERROR); }
/src/main/resources/ValidationMessages.properties
errors.users.mailAddress.duplicated=そのメールアドレス({0})は既に登録されています