#java #spring #spring-boot #jpa #spring-data-jpa
Вопрос:
Я создаю одно приложение Spring Boot, содержащее одну сущность пользователя.
Я хочу реализовать функциональность, в которой администратор может искать пользователей с помощью разных фильтров, и фильтры могут быть одним или несколькими столбцами из таблицы пользователей.
Ниже приведен класс сущности пользователя:
@Getter
@Setter
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@Column(name = "user_id", nullable = false, unique = true, length = 10)
private String userId;
@Column(name = "user_first_name", nullable = false, length = 20)
private String userFirstName;
@Column(name = "user_middle_name", length = 20)
private String userMiddleName;
@Column(name = "user_last_name", nullable = false, length = 20)
private String userLastName;
@Column(name = "user_contact", nullable = false, unique = true, length = 10)
private Long userContact;
@Column(name = "user_email", nullable = false, unique = true, length = 50)
private String userEmail;
@Column(name = "user_password", nullable = false)
private String userPassword;
@Column(name = "user_enabled", nullable = false)
private Boolean userEnabled;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<RoleEntity> userRoles;
@OneToMany(mappedBy = "tokenUser", fetch = FetchType.LAZY)
private Set<TokenEntity> userTokens;
@Temporal(TemporalType.DATE)
@Column(name = "last_updated_on", nullable = false)
private Date lastUpdatedOn;
@Column(name = "last_updated_by", nullable = false)
private String lastUpdatedBy;
@Temporal(TemporalType.DATE)
@Column(name = "created_on", nullable = false)
private Date createdOn;
@Column(name = "created_by", nullable = false)
private String createdBy;
}
При поиске пользователя фильтром может быть только имя, или в какой-то момент и имя, и фамилия могут быть фильтром, или, если требуется, некоторые другие значения столбцов (идентификатор, адрес электронной почты и Контакт) также могут использоваться в качестве фильтров вместе с ними. Выбор фильтров будет полностью зависеть от администратора во время выполнения.
Может ли кто-нибудь, пожалуйста, рассказать мне, как я могу реализовать эту функциональность с помощью JPA и Spring Boot?
Ниже приведены мои классы Контроллера, Службы и Репозитория соответственно.
Пользовательский контроллер
@RestController
@RequestMapping("/bma/api/admin/users")
public class UserController {
@Autowired
private UserService userService;
private final int DEFAULT_PAGE_NUMBER = 1;
private final int DEFAULT_PAGE_SIZE = 5;
@GetMapping("/all")
public ResponseEntity<?> getAllUsers(
@RequestParam(name = "page_number", required = false) Integer pageNumber,
@RequestParam(name = "page_size", required = false) Integer pageSize) {
try {
if (pageNumber == null) pageNumber = DEFAULT_PAGE_NUMBER;
if (pageSize == null) pageSize = DEFAULT_PAGE_SIZE;
List<UserResponseModel> responseModels = userService.getAllUserList(pageNumber-1, pageSize);
GetAllDataResponseMetadata metadata = new GetAllDataResponseMetadata(HttpStatus.FOUND.value(),
pageNumber, pageSize);
return ResponseEntity.status(HttpStatus.FOUND).body(new SuccessResponse<>(metadata, responseModels));
}
catch (NoRecordAvailableException exception) {
CommonResponseMetadataWithMessage metadata =
new CommonResponseMetadataWithMessage(HttpStatus.NOT_FOUND.value(), exception.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse<>(metadata));
}
}
}
UserService
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public UserResponseModel addNewUser(UserRequestModel userRequestModel) {
if (userRepository.existsUserEntityByUserContact(userRequestModel.getUserContact())) {
throw new InformationAlreadyExistsException("Contact Number Already Exists");
}
else if (userRepository.existsUserEntityByUserEmail(userRequestModel.getUserEmail())) {
throw new InformationAlreadyExistsException("Email Already Exists");
}
else {
UserDetailsValidationUtility.isEmailValid(userRequestModel.getUserEmail());
UserDetailsValidationUtility.isContactNumberValid(userRequestModel.getUserContact());
UserDetailsValidationUtility.isNameValid(userRequestModel.getUserFirstName(), false);
UserDetailsValidationUtility.isNameValid(userRequestModel.getUserLastName(), false);
UserDetailsValidationUtility.isNameValid(userRequestModel.getUserMiddleName(), true);
UserDetailsValidationUtility.isPasswordValid(userRequestModel.getUserPassword());
UserEntity newUserEntity = getUserEntityFromModel(userRequestModel);
return getUserResponseModelFromEntity(userRepository.save(newUserEntity));
}
}
public List<UserResponseModel> getAllUserList(int pageNumber, int PageSize) {
Pageable pageWithSpecificNumberOfRecord = PageRequest.of(pageNumber, PageSize);
Page<UserEntity> userEntities = userRepository.findAll(pageWithSpecificNumberOfRecord);
if (userEntities.isEmpty()) {
throw new NoRecordAvailableException("No User Record Available");
}
else {
List<UserResponseModel> userResponseModels = new ArrayList<>();
userEntities.forEach(userEntity ->
userResponseModels.add(getUserResponseModelFromEntity(userEntity)));
return userResponseModels;
}
}
private UserResponseModel getUserResponseModelFromEntity(UserEntity existingUserEntity) {
UserResponseModel responseModel = new UserResponseModel();
responseModel.setUserId(existingUserEntity.getUserId());
responseModel.setUserFullName(buildFullNameOfUser(existingUserEntity));
responseModel.setUserContact(existingUserEntity.getUserContact());
responseModel.setUserEmail(existingUserEntity.getUserEmail());
return responseModel;
}
private UserEntity getUserEntityFromModel(UserRequestModel userRequestModel) {
Date currentDateTime = BankManagementUtility.getCurrentDateTime();
String userId = generateUserId();
UserEntity newUserEntity = new UserEntity();
newUserEntity.setUserId(userId);
newUserEntity.setUserFirstName(userRequestModel.getUserFirstName().trim());
if (userRequestModel.getUserMiddleName() == null)
newUserEntity.setUserMiddleName("");
else newUserEntity.setUserMiddleName(userRequestModel.getUserMiddleName().trim());
newUserEntity.setUserLastName(userRequestModel.getUserLastName().trim());
newUserEntity.setUserContact(userRequestModel.getUserContact());
newUserEntity.setUserEmail(userRequestModel.getUserEmail().trim());
newUserEntity.setUserPassword(passwordEncoder.encode(userRequestModel.getUserPassword().trim()));
newUserEntity.setUserEnabled(false);
newUserEntity.setLastUpdatedOn(currentDateTime);
newUserEntity.setLastUpdatedBy(userId);
newUserEntity.setCreatedOn(currentDateTime);
newUserEntity.setCreatedBy(userId);
newUserEntity.setUserTokens(new HashSet<>());
newUserEntity.setUserRoles(new HashSet<>());
newUserEntity.getUserRoles().add(roleRepository.findRoleEntityByRoleName("USER"));
return newUserEntity;
}
private String generateUserId() {
StringBuilder userId = new StringBuilder("USER");
userId.append(BankManagementUtility.generateNumberIdNumberByDigit(6));
if (userRepository.existsUserEntityByUserId(userId.toString())) {
return generateUserId();
}
else return userId.toString();
}
private String buildFullNameOfUser(UserEntity userEntity) {
StringBuilder fullName = new StringBuilder(userEntity.getUserFirstName());
if (!userEntity.getUserMiddleName().isEmpty()) {
fullName.append(" ");
fullName.append(userEntity.getUserMiddleName());
}
fullName.append(" ");
fullName.append(userEntity.getUserLastName());
return fullName.toString();
}
}
Информация для пользователей
@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {
UserEntity findUserEntityByUserEmail(String email);
UserEntity findUserEntityByUserId(String id);
Boolean existsUserEntityByUserId(String id);
Boolean existsUserEntityByUserEmail(String email);
Boolean existsUserEntityByUserContact(Long contact);
}
Также вот ссылка на репозиторий GitHub, если кто — то хочет взглянуть на весь проект:
https://github.com/rajeshsinha1997/Centralised_Banking_System_Application
Помимо вышеупомянутого запроса, если у кого-то есть какие-либо другие советы/предложения относительно кода или проекта, это будет оценено.
Ответ №1:
Я думаю, что лучший способ для вас-создать другую конечную точку, которая получает объект JSON с критериями поиска. Например:
{
"userFilter": {
"userId": "1",
"userFirstName": "John",
"userLastName": "Doe",
"userEmail": "john.doe@johndoe.com"
}
}
В конечной точке замените все атрибуты «null» на «*». Таким образом, вы можете сгенерировать запрос, в котором все данные будут возвращены для определенного атрибута, если он не входит в параметры фильтра.
@PostMapping("/filter")
public ResponseEntity<?> filterUsers(@RequestBody UserFilter userFilter) {
if(userFilter.getUserId() == null) {
userFilter.setUserId("*");
}
// ... do this for all parameters of userFilter ...
return ResponseEntity.body(userService.filterUsers(userFilter.getId(), userFilter.getUserFirstName(), userfilter.getUserLastName(), userFilter.getUserEmail()));
}
Затем, в хранилище, я бы сделал что-то вроде этого:
@Query("SELECT u FROM User u WHERE u.id like CONCAT('%', :id, '%') and u.first_name like CONCAT('%', :firstName, '%') and u.last_name like CONCAT('%', :lastName, '%') and u.email like CONCAT('%', :email, '%')")
List<User> filterUsers(@Param("id") Integer id, @Param("firstName") String firstName, @Param("lastName") String lastName, @Param("email") String userEmail);
Для справки по JPQL: https://www.baeldung.com/spring-data-jpa-query