Entity
You already provided your entity, but i added the missing annotations so it can be picked up by any jpa implementation. Just a quick reminder here, whenever you store a password you should consider hashing passwords and not store them as plaintext in your database. You can find more information about this here.
@Entity
@Table(name = "user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
private Long id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "firstName")
private String firstName;
@Column(name = "lastName")
private String lastName;
// remainer ommitted for brevity
}
Repository
The most simple option is to create methods using Spring Data JPA.
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
Optional<User> findOneByUsername(String username);
List<User> findAllByFirstName(String firstName);
List<User> findAllByLastName(String lastName);
}
However, consider the case where you might want to query users for more attributes at the same time. For example, if you want to find a user by firstName
, lastName
, gender
, phoneNumber
, ... it would be impossible to write methods for all sorts of combinations.
findAllByFirstNameAndLastNameAndGenderAndPhoneNumber // pretty confusing
If you only need a few properties, you can use CrudRepository
as stated above, if you need more properties you might want to have a look at QueryDSL or Specifications, which deal exactly with that problem. More information about this here.
Service
Next up, you should create a service to decouple your data layer.
@Service
public class UserService {
private UserRepository repository;
@Autowired
public UserService(UserRepository repository) {
this.repository = repository;
}
Optional<User> findOneByUsername(String username) {
return repository.findOneByUsername(username);
}
List<User> findAllByFirstName(String firstName) {
return repository.findAllByFirstName(firstName);
}
List<User> findAllByLastName(String lastName) {
return repository.findAllByLastName(lastName);
}
}
Controller
Finally, create a controller to access you service layer.
@RestController
@RequestMapping("/users")
public UserController {
private UserService service;
@Autowired
public UserController(UserService service) {
this.service = service;
}
@GetMapping()
@ResponseBody
public List<User> findAll(@RequestParam(value = "username", required = false) String username,
@RequestParam(value = "firstName", required = false) String firstName,
@RequestParam(value = "lastName", required = false) String lastName) {
if (username != null) {
return List.of(service.findOneByUsername(username));
}
if (firstName != null) {
return service.findAllByFirstName(username);
}
if (lastName!= null) {
return service.findAllByLastName(username);
}
return service.findAll();
}
}
One last note here, think about whether you want to make you password field also available in requests, if not i would recommend using a UserDTO and ModelMapper.