I am trying to fetch User data using userName in Spring JPA repository, but it always returns an empty list - spring

I am using below code to fetch user information from MySQL database using username, but it always returns empty list.
public interface UserRepository extends JpaRepository<User, Integer> {
List<User> findByUserNameIgnoreCase(String userName);
}
The below method is in service class
public String login(LoginDTO loginDTO) {
logger.info("Login request for customer {} with password {}",
loginDTO.getUserName(), loginDTO.getPassword());
List<User> user =
userRepo.findByUserNameIgnoreCase(loginDTO.getUserName());
if(user.isEmpty())
return "Invalid";
else
return "Successful";
}
Kindly help.

Trying findByUsernameIgnoreCase because Spring might treat it as User and Name instead of Username.

Related

Is there a JpaRepository method which can save a provided password where username condition?

I am looking for a JpaRepository method to update a user provided password at the time of resetting it with a username condition . Thanks in advance
Have a look at creating custom query methods with JPA as per documentation: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query.
For your use case, the following would allow you update the correct user's password:
#Repository
public interface UserRepository extends JpaRepository<User, UUID> {
#Query("update User u set u.password= ?1 where u.username = ?2")
void updatePassword(String username, String password);
}
In Spring Data JPA, whenever you execute an update, you need to use the #Modifying along with the #Query. Failing to use the #Modifying will result in InvalidDataAccessApiUsage exception.
Find the code below
#Repository
public interface UserRepository extends JpaRepository<User, UUID> {
#Modifying
#Query("update User u set u.password= :password where u.username = :username")
void updatePassword(#Param("username") String username, #Param("password") String password);
}

Best approach to create different JSON response from same Entity

I have an entity class User with 20 fields, some of them being confidential fields. I have a controller class, which has a method getUser to fetch all the user from DB and send the JSON respone. Below is the sample code for the same:
#GetMapping("/getUsers")
public UserDT getUsers( Model theModel) {
List<User> userList;
userList = userService.findAll();
return userList;
}
When I run the above code, it returns all the fields from User table/User Entity Class. Instead of sending all the fields, I would like to send selected fields say Field1 to Field5 only.
Ultimate goal is to have multiple views for the same Entity Class. For URL1 I would like to show only field1 to field5 of User table, But for URL2 I would like to show Field9 , Filed15, Field20.
Do I need to create multiple Entity Class for each URL? Please guide me with the best practice to be followed in such scenario.
Assuming you are using Spring Data JPA, use projections.
So create different projections for your different URLs write a method that returns the projection (or a dynamic one as in the documentation).
public interface NamesOnlyProjection {
String getFirstName();
String getLastName();
}
public interface UserinfoProjection {
String getUsername();
String getPassword();
String getDepartment();
}
Then in your repository do something like this
public interface PersonRepository extends JpaRepository<Person, Long> {
<T> List<T> findAll(Class<T> type);
}
Then you can do something like this in your controller/service
#RestController
public class PersonController {
private final PersonRepository persons;
#GetMapping("/people/names")
public List<NamesOnlyProjection> allNames() {
return persons.findAll(NamesOnlyProjection.class);
}
#GetMapping("/people/users")
public List<UserinfoProjection> allNames() {
return persons.findAll(UserinfoProjection.class);
}
}

At what positions I can use #Cacheable in spring boot with redis cache

At what positions I can use #Cacheable in spring boot with redis cache,
Can I use it with any method?
public UserDTO findByUserID(Long userID) {
User user = findUser(userID);
if (user != null) {
Password password = findPassword(userID);
return userMapper.mapToDTO(user, password);
}
return null;
}
private Password findPassword(Long userID) {
Password password = passwordRepository.findPasswordBasedOnUserID(userID);
return password;
}
#Cacheable("users")
private User findUser(Long userID) {
User user = userRepository.findByUserID(userID);
return user;
}
I have used it with method findUser because findByUserID returns the DTO which is obviously not an entity, so to get rid of it I created two methods that returns domain, but problem is that it is not saving or use redis cache, can anybody suggest me the problem or any solution?
No, you can't have it on private method of same service, because Spring does not handle calls to private methods of same class. You should move findUser or findByUserId to other service.

Externalize mongo json query using spring boot

I have just started using spring data MongoDb with Spring-Boot.
I have some mongo based json queries added in the interface using #query annotation when using spring data repository.
I want to know if it is possible to externalize or separate out the JSON query outside the codebase so that it can be optimized separately and
also not having it mixed with code.
Thanks for your suggestions.
This is the code which i have added in my interface and annotated with #query annotation.
#Query("{ 'firstname' : ?0 ,'lastname': ?1}")
List findByCriteria(String firstname,String lastname);
The above is a simple example. I have complex conditions involving $and and $or operators too .
What i basically want to achieve is externalize the above native mongo json query to a config file and refer that in the above annotation.
Spring data supports something similar when using jpa with hibernate. But not sure if we can do the same using spring data mongodb with spring boot.
Do like this (I am explaining only for the API)
Suppose you have an Entity user
At the Top there will be User domain
public class User extends CoreDomain {
private static final long serialVersionUID = -4292195532570879677L;
#Length(min = 2)
private String name;
#Length(min = 2)
#UniqueUserName(message = "User name already registered,Please choose something Different")
private String userName;
#Length(min = 6)
private String password;
}
User Controller
User Service (Interface)
User ServiceImpl(Service Implementation)
Mongo Repository(Since, I have MongoDb)
Now in userController you will take all the queries , Param(Parameters) , Pagerequest like this
public class UserController extends CoreController {
#Autowired
private UserService userService;
/*
* This controller is for getting the UserDetails on passing the UserId in
* the #param Annotation
*/
#GET
#Path("{id}")
public User getUser(#PathParam("id") String UserId) {
User user = new User();
user = userService.findUserId(UserId);
if (user == null)
throw new NotFoundException();
log.info("The userId you searched is having the details as :" + user);
return user;
}}
For serviceInterface you will have :
public interface UserService {
// Boolean authenticateUser(User user);
User findUserId(String UserId);
}
For serviceImpl :
public class UserServiceImpl implements UserService {
#Setter
#Autowired
private UserRepository userRepository;
/*
* This method will find user on the basis of their userIds passed in the
* parameter.
*/
#Override
public User findUserId(String UserId) {
User userIdResult = userRepository.findOne(UserId);
log.info("The userDetail is" + userIdResult);
return userIdResult;
}
In mongoRepository for user we will have:
A default query findById(String userId);
Hopefully this will help you.

How to use OpenSessionInViewInterceptor?

Consider entity
public class User {
...
#OneToMany(cascade = CascadeType.ALL)
List<SocialCredential> credentialsList = new ArrayList<SocialCredential> ();
}
with DAO Implementation method
#Transactional
#Override
public User getUser(long id){
Session s = sessionFactory.getCurrentSession();
User u = (User) s.get(User.class, id);
return u;
}
and Controller
#Controller
public class DummyController {
#Autowired
UserDAO userDAO;
public void anyMethodAccessedByGetORPost(){
User u= userDAO.getUser(1L);
}
}
A simple query for entity User automatically fires query to initialize entity list of SocialCredential ? Ultimately it leads to LazyInitializationException.I came to know to know about OpenSessionInViewInterceptor which can solve the issue.How can I apply the same. I am already following http://www.jroller.com/kbaum/entry/orm_lazy_initialization_with_dao but with no success so far.
A simple query for entity User automatically fires query to initialize entity list of SocialCredential ?
It depends on underlying persistence API's default fetch type.
Refer this question
Ultimately it leads to LazyInitializationException -- This is probably you are trying access credentialsList collection after session has been closed.
Replace DAO's getUser(Long id) method with below code may solve LazyInitializationException.
#Transactional
#Override
public User getUser(long id){
Session s = sessionFactory.getCurrentSession();
User u = (User) s.get(User.class, id);
if (u != null) {
u.getCredentialsList(); //it loads the SocialCredentials before session closes.
}
return u;
}

Resources