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.
Related
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.
I have already done user register and login. But I want to encrypt the password when create a profile.
This is my current configuration
MongoDB Connection
spring.data.mongodb.uri= mongodb://127.0.0.1:27017/Student
server.port=8080
Model Class:
#Document
#AllArgsConstructor
#NoArgsConstructor
#Data
public class User {
#Id
#Indexed
private String id;
#Indexed
private String address;
#Indexed
private String name;
#Indexed
private String email;
#Indexed
private String password;
#Indexed
private String role;
}
Repository Class:
public interface userReporsitory extends MongoRepository<User,String> {
Optional<User> findByEmail(String email);
List<User> findAllByRole(String role);
}
Service Class:
#AllArgsConstructor
#Service
public class userService {
private userReporsitory userReporsitory;
public User saveUser(User user){
return userReporsitory.save(user);
}
public User login(User user){
User response = userReporsitory.findByEmail(user.getEmail()).orElseThrow(()->new RuntimeException("User Not Found"));
if(!response.getPassword().equals(user.getPassword())){
throw new RuntimeException("Bad Credincials");
}
return response;
}
public List<User> findAllUsers(){
return userReporsitory.findAllByRole("user");
}
}
Controller Class:
#CrossOrigin
#RestController
#AllArgsConstructor
#RequestMapping("api/v1/user")
public class userController {
private userService userService;
#PostMapping("/create")
public ResponseEntity<User> save(#RequestBody User user){
HttpStatus status = HttpStatus.EXPECTATION_FAILED;
User response = userService.saveUser(user);
if(response != null){
status = HttpStatus.CREATED;
}
return new ResponseEntity<>(response, status);
}
#PostMapping("/login")
public ResponseEntity<User> login(#RequestBody User user){
return new ResponseEntity<>(userService.login(user),HttpStatus.ACCEPTED);
}
#GetMapping("/userList")
public ResponseEntity<List<User>> userList(){
return new ResponseEntity<>(userService.findAllUsers(),HttpStatus.ACCEPTED);
}
}
Use
BCryptPasswordEncoder
Class while saving the Password in DataBase.it will convert the normal text to RandomValue.
Define the BCryptPasswordEncoder In config Class.
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
Repository Class :
#Autowired
private PasswordEncoder passwordEncoder;
public User newUserAccount(UserDto accountDto) {
User user = new User();
user.setFirstName(accountDto.getFirstName());
user.setLastName(accountDto.getLastName());
user.setPassword(passwordEncoder.encode(accountDto.getPassword()));
return repository.save(user);
}
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
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'm a novice java developer and now develop User Management application using Spring-Hibernate. I have two entities User and Email. And User entity has a field Email which is mapped to Email entity as #ManyToOne. Any Email can be used by multiple users.
When I save a new User in DB for every new user I get a new row Email, even if the same record is already in the Email Table. How to properly make save operation to avoid duplication of the same records in the table Email?
User.java
#Entity
#Table(name = "USER")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="ID")
private Long id;
#Column(name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "email_id")
private Email email;
public User(){
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
...
}
Email.java
#Entity
#Table(name = "EMAIL")
public class Email implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="ID")
private Long id;
#Column(name = "emailaddress")
private String emailaddress;
#OneToMany (mappedBy = "email", targetEntity=User.class)
private Set<User> user= new HashSet<User>();
public Email() {
}
public Email(String emailaddress) {
this.emailaddress = emailaddress;
}
public String getEmailaddress() {
return emailaddress;
}
public void setEmailaddress(String emailaddress) {
this.emailaddress = emailaddress;
}
...
}
Controller.java
#Transactional
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
public String saveOrder(#ModelAttribute("user") User user, BindingResult result, #RequestParam String action){
emailDAO.create(user.getEmail());
userDAO.create(user);
return "index";
...
}
EmailDAO.java
#Transactional
#Repository
public class EmailDAO{
#Autowired
private SessionFactory sessionFactory;
public Email create(Email email) {
sessionFactory.getCurrentSession().save(email);
return email;
}
}
UserDAO.java
#Transactional
#Repository
public class UserDAO{
#Autowired
private SessionFactory sessionFactory;
public User create(User user) {
sessionFactory.getCurrentSession().save(user);
return user;
}
}
webform.jsp
<form:form action="${formUrl}" method="post" modelAttribute="user">
<form:label path="name" for="appname">username</form:label>
<form:input path="name" id= "appname" cssClass="form-control"/>
<form:label path="email.emailaddress" for="appemail">Email</form:label>
<form:input path="email.emailaddress" id= "appemail"/>
<button type="submit" name="action" value="Add">Save</button>
</form:form>
database diagram
Example of the DB records
That is because you keep on saving the Email as a new Record
#Transactional
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
public String saveOrder(#ModelAttribute("user") User user, BindingResult result, #RequestParam String action){
emailDAO.create(user.getEmail()); // Inserting Email as New Record
userDAO.create(user);
return "index";
...
}
And you don't have unique=true on Email Entity
#Column(name = "emailaddress", unique = true)
private String emailaddress;
Which you should ideally have so that there will be no duplicate Emails will get inserted even by accidentally.
You need to modify EmailDAO
#Transactional
#Repository
public class EmailDAO{
#Autowired
private SessionFactory sessionFactory;
public Email create(Email email) {
sessionFactory.getCurrentSession().save(email);
return email;
}
public Email getEmail(String inputEmail) {
Email email = null;
Query query = sessionFactory.getCurrentSession().createQuery("FROM Email e WHERE e.emailaddress = :email");
query.setString("email", inputEmail);
List emails = query.list();
if(emails != null && emails.size() > 0) {
email = (Email)emails.get(0);
} else {
email = new Email();
email.setEmailAddress(inputEmail);
}
return email;
}
}
And you getEmail
#Transactional
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
public String saveOrder(#ModelAttribute("user") User user, BindingResult result, #RequestParam String action){
user.setEmail(emailDAO.getEmail(user.getEmail().getEmailAddress())); // Inserting Email as New Record
userDAO.create(user);
return "index";
...
}