I have UserDto.
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ApiModel(value = "UserDto", description = " DTO User ")
public class UserDto {
private Long userId;
private String firstName;
private String lastName;
private LocalDate dateOfBirth;
private String education;
private String aboutMe;
I need to create update method.That's what I have now.
#PatchMapping("/{user}/edit")
public ResponseEntity<String> update(#RequestBody UserDto userDto, #PathVariable long id) {
Optional<User> optionalUser = userService.getById(id);
if (!optionalUser.isPresent()) {
return ResponseEntity
.badRequest()
.body("Пользователь не найден");
}
User user = optionalUser.get();
userService.update(user);
return new ResponseEntity<>(HttpStatus.OK);
}
How can I use Dto to partial update user data? I assume I need a converter. Thanks!
You must create a constructor in Entity class and transform fields from dto to entity
Related
Based on my question above, I have a table named User. I want to display all the data based on two parameters, status and createdBy. For example, if the user key is in both params, it will show based on both params. If the user just want to key in status = 1 and the createdBy remains empty, the data will show only with status = 1. The same goes for when the user only wants to key in createdBy. If the user does not key in both param, it will display all data.
Now. I only can do this if the user key in both param. Below is my code:
User.java
#Table(name = "idr_user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
private int status;
#Column(name="factory_id", nullable = true)
private int factoryId;
#Column(name="created_by", nullable = true)
private Integer createdBy;
#Column(name="role_id", nullable = true)
private Integer roleId;
}
UserResponseDto.java
public class UserResponseDto {
private int id;
private String name;
private String email;
private Integer factoryId;
private Integer status;
private Integer createdBy;
private Integer roleId;
}
UserRepository
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
public List<User> findAllUserByStatusAndCreatedBy(Optional<Integer> status, Optional<Integer> createdBy);
}
UserController
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#GetMapping(path="user/statusAndCreatedBy/{status}/{createdBy}")
public #ResponseBody Iterable<UserResponseDto> getUserByStatusAndCreatedBy(#PathVariable Optional<Integer> status, #PathVariable Optional<Integer> createdBy) {
return userService.getUserByStatusAndCreatedBy(status, createdBy).stream().map(user -> modelMapper.map(user, UserResponseDto.class)).collect(Collectors.toList());
}
}
UserService.java
public class UserService {
#Autowired
private UserRepository userRepository;
public List<User> getUserByStatusAndCreatedBy(Optional<Integer> status, Optional<Integer> createdBy) {
return userRepository.findAllUserByStatusAndCreatedBy(status, createdBy);
}
}
Hence, anyone can help? Im stuck at this. Thank you
You can use JPA specifications for optional parameter filtering
Example:
userRepository.findAll(isStatus(status).and(isCreatedBy(createdBy)));
Here, create isStatus() and isCreatedBy() function using specification.
Read here for how to write specification : https://www.stackhawk.com/blog/using-jpa-specifications-with-kotlin/
Based on my question above, Below is my code.
UserService
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public List<User> getUserByIdAndEmail(Long id, String email) {
return userRepository.findByIdAndEmail(id, email);
}
}
UserRepository
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
public User findUserByEmail(String email);
public List<User> findByIdAndEmail(long id, String email);
}
UserController
#RestController
public class UserController {
#Autowired
private UserService userService;
#Autowired
private ModelMapper modelMapper;
#GetMapping(path="user/idEmail/{id}/{email}")
public #ResponseBody UserDto getUserByIdAndEmail(#PathVariable long id, #PathVariable String email) {
return modelMapper.map(userService.getUserByIdAndEmail(id, email), UserDto.class);
}
}
User
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#Table(name = "idr_user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
UserDto
#Data
public class UserDto {
private int id;
private String name;
private String email;
}
And when i enter the correct ID and Email the result is null.
Can I know which part that I missing?
Change
public List<User> findByIdAndEmail(long id, String email);
to
public Optional<User> findByIdAndEmail(long id, String email);
then apply logic if the optional is present.
You shouldn't expect a list in this case as the ID is a primary key, therefor no duplicate. Even if you have duplicated emails, as long as you use id, you won't receive a list.
My controller:
#PostMapping
public ResponseEntity<UserCreateResponse> createUser(#RequestBody #Valid UserCreateRequest userDto,
BindingResult result)
throws InvalidRequestException {
if (result.hasErrors()) {
throw new InvalidRequestException("Request parameter validation failed");
} else {
return ResponseEntity.ok(userService.createUser(userDto));
}
}
Service:
public UserCreateResponse createUser(UserCreateRequest userDto) {
return convertEntityToDto(userRepository.insert(convertDtoToEntity(userDto)));
}
private User convertDtoToEntity(UserCreateRequest userDto) {
return modelMapper.map(userDto, User.class);
}
private UserCreateResponse convertEntityToDto(User user) {
return modelMapper.map(user, UserCreateResponse.class);
}
And the model is :
#Getter
#Setter
#Document("User")
public class User {
#Id
private String id;
#Indexed(unique = true)
private String userName;
private String name;
private String surname;
private String job;
}
Repository is just a class extending MongoRepository.
When I try to insert 2 User with same userName via postman post request, it is adding 2 exactly same item to db even if I specified #Indexed(unique = true) to userName field. Why does this happen and how can I fix it on Java side without breaking indexing function on the field(I want to index userName field to find faster)
I have produced a DTO object from 2 microservices. Profile and ProfileCredit. I am able to successfully retrieve a populated DTO object with relevant data. However I am further curious is it possible to query or do conditional filter on the generated DTO object? and if so what is the approach to achieve just that?
For example using 'swagger' this is what gets returned
Is it possible to filter by profileCredit field which is present in the dto but the data is retrieved within separate microservice?
Any help, suggestions or references to any other posts or pages would be truly helpful.
Controller
#GetMapping(path="/profile/search/username/{username}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<Page<ProfileCreditDTO>> findProfileByUsername(#PathVariable String username, Pageable pageable) {
Page<ProfileCreditDTO> results= profileCreditService.findProfileBySelectedParameters(username,pageable);
if(results== null){
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else
return new ResponseEntity<>(results,HttpStatus.OK);
}
Query within profileCreditService
#Query("SELECT p from PROFILES p where lower(p.username) LIKE :username%")
Page<ProfileCreditDTO> findProfileBySelectedParameters(String username, Pageable pageable);
ProfileCreditServiceImpl
public ProfileCreditDTO findProfileCreditByProfileId(final Long profileId){
log.info("Start of findProfileCreditByProfileId method {}",profileId);
ProfileCreditDTO rc= new ProfileCreditDTO();
Profile profile=profileRepository.findOne(profileId);
if(profile == null){
return null; }
CreditDTO creditDto= profileCreditClient.findClientByProfileId(profile.getId());
if(creditDto == null){
return null; }
rc.setProfile(profile);
rc.setCredit(creditDto);
return rc;
}
private ProfileCreditDTO convertProfileToProfileCreditDTO(final Profile theProfile){
if(theProfile == null)
return null;
ProfileCreditDTO theDTO= new ProfileCreditDTO();
theDTO.setProfile(theProfile);
CreditDTO theCreditDto= profileCreditClient.findClientByProfileId(theProfile.getId());
if(theCreditDto != null )
theDTO.setCredit(theCreditDto);
return theDTO;
}
Profile Domain
#Entity(name = "PROFILES")
#Data #NoArgsConstructor #AllArgsConstructor
#ToString
public class Profile implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#Size(min = 2, max = 20)
private String username;
private Integer profileType;
private Integer gender;
private Integer orientation;
private boolean online;
#JsonFormat(pattern="uuuu-MM-dd'T'HH:mm:ss.SSS")
private LocalDateTime created;
#JsonFormat(pattern="uuuu-MM-dd'T'HH:mm:ss.SSS")
private LocalDateTime lastEdited;
Profile Credit DTO
#Data
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class ProfileCreditDTO {
//profile fields
private Long profileId;
#Size(min = 2, max = 50)
private String username;
private Integer gender;
private Integer profileType;
private Integer orientation;
private boolean online;
// Credit fields
private Long creditId;
#Column(unique = true)
private double profileCredit;
public void setProfile(final Profile profile) {
this.setProfileId(profile.getId());
this.setUsername(profile.getUsername());
this.setGender(profile.getGender());
this.setProfileType(profile.getProfileType());
this.setOrientation(profile.getOrientation());
this.setOnline(profile.isOnline());
}
public void setCredit(final CreditDTO credit){
this.setCreditId(credit.getId());
this.setProfileCredit(credit.getProfileCredit());
}
ProfileCreditClient (feign)
#Component
#FeignClient(name = "profileCreditService")
public interface ProfileCreditClient {
#GetMapping("/api/credit/profile/{profileId}")
CreditDTO findClientByProfileId(#PathVariable("profileId") Long clientId);
}
Profile Repository Query
#Query("SELECT p from PROFILES p where lower(p.username) LIKE :username%")
Page<Profile> findByAllParameters(#Param("username") String username, Pageable pageable);
I Have method in service to save user after registration, but after method invocation I have two same documents in collection.
Controller:
#RequestMapping(value="/registration/male", method= RequestMethod.POST, consumes={ MediaType.APPLICATION_JSON_VALUE })
public #ResponseBody void maleRegistration (#RequestBody MaleDTO maleDTO, HttpServletRequest request) throws EmailExistsException {
User user = registrationService.maleRegistration(maleDTO);
autoLogin(user, request);
}
Method in service:
#Transactional
public User maleRegistration(MaleDTO male) throws EmailExistsException {
if (userRepository.existsByEmail(male.getEmail())) {
throw new EmailExistsException("There is an account with that email address: " + male.getEmail());
}
User user = new User();
user.setName(male.getName());
user.setGender(Gender.MALE);
user.setDateOfBirth(male.getDateOfBirth());
user.setEmail(male.getEmail());
user.setPassword(encoder.encode(male.getPassword()));
user.setRoles(new HashSet<>(Arrays.asList(Role.ROLE_USER)));
userRepository.save(user);
return user;
}
User repository:
public interface UserRepository extends MongoRepository<User, String>{
}
User Class:
#Document(collection = "Users")
public class User {
#Id
private String id;
private String name;
private Gender gender;
private LocalDate dateOfBirth;
private String email;
private String password;
private Set<Role> roles;
//geters and seters
//toString
}
Why it happens?
I would appreciate any help.