I have two entities User and Phone.
User Entity:
@Table(name = "user_table")
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "username", unique = true, nullable = false)
@Column(name = "firstname")
private String firstName;
@Column(name = "lastname")
@Column(name = "email", nullable = false, unique = true)
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", foreignKey = @ForeignKey(name = "fk_user_address_id"))
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "phone_number", foreignKey = @ForeignKey(name = "fk_user_phone_number"))
private Instant createdAt;
private Instant updatedAt;
public String toString() {
return String.format("User{id = %d," +
"Phone Number = %s}", id, username, firstName, lastName, age, email,address, phone);
public boolean equals(Object o) {
if (this == o) return true;
if(o==null || getClass()!=o.getClass()) return false;
return username.equals(user.username);
return Objects.hash(username);
<code>@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "user_table")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "username", unique = true, nullable = false)
@NonNull
private String username;
@Column(name = "firstname")
@NonNull
private String firstName;
@Column(name = "lastname")
@NonNull
private String lastName;
@Column(name = "age")
@NonNull
private Integer age;
@Column(name = "email", nullable = false, unique = true)
@NonNull
private String email;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", foreignKey = @ForeignKey(name = "fk_user_address_id"))
private Address address;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "phone_number", foreignKey = @ForeignKey(name = "fk_user_phone_number"))
private Phone phone;
@CreatedDate
private Instant createdAt;
@LastModifiedDate
private Instant updatedAt;
@CreatedBy
private UUID createdBy;
@Override
public String toString() {
return String.format("User{id = %d," +
"UserName = %s," +
"FirstName = %s," +
"LastName = %s," +
"Age = %d," +
"Email = %s," +
"Address = %s," +
"Phone Number = %s}", id, username, firstName, lastName, age, email,address, phone);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if(o==null || getClass()!=o.getClass()) return false;
User user = (User) o;
return username.equals(user.username);
}
@Override
public int hashCode() {
return Objects.hash(username);
}
}
</code>
@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "user_table")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "username", unique = true, nullable = false)
@NonNull
private String username;
@Column(name = "firstname")
@NonNull
private String firstName;
@Column(name = "lastname")
@NonNull
private String lastName;
@Column(name = "age")
@NonNull
private Integer age;
@Column(name = "email", nullable = false, unique = true)
@NonNull
private String email;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", foreignKey = @ForeignKey(name = "fk_user_address_id"))
private Address address;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "phone_number", foreignKey = @ForeignKey(name = "fk_user_phone_number"))
private Phone phone;
@CreatedDate
private Instant createdAt;
@LastModifiedDate
private Instant updatedAt;
@CreatedBy
private UUID createdBy;
@Override
public String toString() {
return String.format("User{id = %d," +
"UserName = %s," +
"FirstName = %s," +
"LastName = %s," +
"Age = %d," +
"Email = %s," +
"Address = %s," +
"Phone Number = %s}", id, username, firstName, lastName, age, email,address, phone);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if(o==null || getClass()!=o.getClass()) return false;
User user = (User) o;
return username.equals(user.username);
}
@Override
public int hashCode() {
return Objects.hash(username);
}
}
Phone Entity :
@Table(name = "phone_table")
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "phone_number", unique = true, nullable = false)
public String toString() {
return "Phone [id = " + id + ", phone = " + number + "]";
return Objects.hash(number);
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if(getClass() != obj.getClass()) return false;
Phone phoneNumber = (Phone) obj;
return number.equals(phoneNumber.number);
<code>@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "phone_table")
public class Phone {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "phone_number", unique = true, nullable = false)
@NonNull
private String number;
@Override
public String toString() {
return "Phone [id = " + id + ", phone = " + number + "]";
}
@Override
public int hashCode() {
return Objects.hash(number);
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if(getClass() != obj.getClass()) return false;
Phone phoneNumber = (Phone) obj;
return number.equals(phoneNumber.number);
}
}
</code>
@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "phone_table")
public class Phone {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "phone_number", unique = true, nullable = false)
@NonNull
private String number;
@Override
public String toString() {
return "Phone [id = " + id + ", phone = " + number + "]";
}
@Override
public int hashCode() {
return Objects.hash(number);
}
@Override
public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null) return false;
if(getClass() != obj.getClass()) return false;
Phone phoneNumber = (Phone) obj;
return number.equals(phoneNumber.number);
}
}
Also I created a DTO classes of these Entities.
public class CreateUserRequest {
private String firstName;
private CreatePhoneRequest phone;
private CreateAddressRequest address;
public class UserResponse {
private String firstName;
private PhoneResponse phone;
private AddressResponse address;
public String toString() {
return String.format("User{id = %d," +
"Phone Number = %s}", id, username, firstName, lastName, age, email,address, phone);
<code>@Data
@Accessors(chain = true)
public class CreateUserRequest {
private Long userId;
private String username;
private String firstName;
private String lastName;
private Integer age;
private String email;
private CreatePhoneRequest phone;
private CreateAddressRequest address;
}
@Data
@Accessors(chain = true)
public class UserResponse {
private Long id;
private String username;
private String firstName;
private String lastName;
private String email;
private int age;
private PhoneResponse phone;
private AddressResponse address;
@Override
public String toString() {
return String.format("User{id = %d," +
"UserName = %s," +
"FirstName = %s," +
"LastName = %s," +
"Age = %d," +
"Email = %s," +
"Address = %s," +
"Phone Number = %s}", id, username, firstName, lastName, age, email,address, phone);
}
}
</code>
@Data
@Accessors(chain = true)
public class CreateUserRequest {
private Long userId;
private String username;
private String firstName;
private String lastName;
private Integer age;
private String email;
private CreatePhoneRequest phone;
private CreateAddressRequest address;
}
@Data
@Accessors(chain = true)
public class UserResponse {
private Long id;
private String username;
private String firstName;
private String lastName;
private String email;
private int age;
private PhoneResponse phone;
private AddressResponse address;
@Override
public String toString() {
return String.format("User{id = %d," +
"UserName = %s," +
"FirstName = %s," +
"LastName = %s," +
"Age = %d," +
"Email = %s," +
"Address = %s," +
"Phone Number = %s}", id, username, firstName, lastName, age, email,address, phone);
}
}
and
public class CreatePhoneRequest {
public class PhoneResponse {
<code>@Data
@Accessors(chain = true)
public class CreatePhoneRequest {
private String phone;
}
@Data
@Accessors(chain = true)
public class PhoneResponse {
private String phone;
}
</code>
@Data
@Accessors(chain = true)
public class CreatePhoneRequest {
private String phone;
}
@Data
@Accessors(chain = true)
public class PhoneResponse {
private String phone;
}
Then UserRepository extends JpaRepository<Long, User>
where I findUserByPhone_Number(String phonenumber
)
in service I make the logic for looking for users:
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final PhoneServiceImpl phoneServiceImpl;
// ***********************************************************
// ******************* GETTING ALL USERS *********************
// ***********************************************************
@Transactional(readOnly = true)
public List<UserResponse> getAllUsers() {
return userRepository.findAll()
.map(this::buidUserResponse)
.collect(Collectors.toList())
private UserResponse buidUserResponse(@NonNull User user) {
return new UserResponse()
.setUsername(user.getUsername())
.setFirstName(user.getFirstName())
.setLastName(user.getLastName())
.setEmail(user.getEmail())
.setAddress(new AddressResponse()
.setCountry(user.getAddress().getCountry())
.setCity(user.getAddress().getCity())
.setStreet(user.getAddress().getStreet())
.setBuildingNumber(user.getAddress().getBuidingNumber())
.setAppt(user.getAddress().getAppt())
.setPhone(new PhoneResponse().setPhone(user.getPhone().getNumber()));
// ***********************************************************
// ******************** FIND USER BY ID **********************
// ***********************************************************
@Transactional(readOnly = true)
public UserResponse findUserById(@NonNull Long id) {
return userRepository.findById(id).map(this::buidUserResponse).orElseThrow(()->new EntityNotFoundException("User not found"));
// ***********************************************************
// ******************* FIND USER BY PHONE ********************
// ***********************************************************
@Transactional(readOnly = true)
public UserResponse getUserByPhoneNumber(String phoneNumber) {
// Phone phone = phoneServiceImpl.getPhoneByNumber(phoneNumber);
// System.out.println(phone);
// UserResponse user = userRepository.getUserByPhone(phone);
// System.out.println(user);
return userRepository.findUserByPhone_Number(phoneNumber);
<code>@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final PhoneServiceImpl phoneServiceImpl;
// ***********************************************************
// ******************* GETTING ALL USERS *********************
// ***********************************************************
@Override
@Transactional(readOnly = true)
public List<UserResponse> getAllUsers() {
return userRepository.findAll()
.stream()
.map(this::buidUserResponse)
.collect(Collectors.toList())
;
}
@NonNull
private UserResponse buidUserResponse(@NonNull User user) {
return new UserResponse()
.setId(user.getId())
.setUsername(user.getUsername())
.setFirstName(user.getFirstName())
.setLastName(user.getLastName())
.setEmail(user.getEmail())
.setAge(user.getAge())
.setAddress(new AddressResponse()
.setCountry(user.getAddress().getCountry())
.setCity(user.getAddress().getCity())
.setStreet(user.getAddress().getStreet())
.setBuildingNumber(user.getAddress().getBuidingNumber())
.setAppt(user.getAddress().getAppt())
)
.setPhone(new PhoneResponse().setPhone(user.getPhone().getNumber()));
}
// ***********************************************************
// ******************** FIND USER BY ID **********************
// ***********************************************************
@Override
@NonNull
@Transactional(readOnly = true)
public UserResponse findUserById(@NonNull Long id) {
return userRepository.findById(id).map(this::buidUserResponse).orElseThrow(()->new EntityNotFoundException("User not found"));
}
// ***********************************************************
// ******************* FIND USER BY PHONE ********************
// ***********************************************************
@NonNull
@Transactional(readOnly = true)
@Override
public UserResponse getUserByPhoneNumber(String phoneNumber) {
// Phone phone = phoneServiceImpl.getPhoneByNumber(phoneNumber);
// System.out.println(phone);
// UserResponse user = userRepository.getUserByPhone(phone);
// System.out.println(user);
return userRepository.findUserByPhone_Number(phoneNumber);
}
}
</code>
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final PhoneServiceImpl phoneServiceImpl;
// ***********************************************************
// ******************* GETTING ALL USERS *********************
// ***********************************************************
@Override
@Transactional(readOnly = true)
public List<UserResponse> getAllUsers() {
return userRepository.findAll()
.stream()
.map(this::buidUserResponse)
.collect(Collectors.toList())
;
}
@NonNull
private UserResponse buidUserResponse(@NonNull User user) {
return new UserResponse()
.setId(user.getId())
.setUsername(user.getUsername())
.setFirstName(user.getFirstName())
.setLastName(user.getLastName())
.setEmail(user.getEmail())
.setAge(user.getAge())
.setAddress(new AddressResponse()
.setCountry(user.getAddress().getCountry())
.setCity(user.getAddress().getCity())
.setStreet(user.getAddress().getStreet())
.setBuildingNumber(user.getAddress().getBuidingNumber())
.setAppt(user.getAddress().getAppt())
)
.setPhone(new PhoneResponse().setPhone(user.getPhone().getNumber()));
}
// ***********************************************************
// ******************** FIND USER BY ID **********************
// ***********************************************************
@Override
@NonNull
@Transactional(readOnly = true)
public UserResponse findUserById(@NonNull Long id) {
return userRepository.findById(id).map(this::buidUserResponse).orElseThrow(()->new EntityNotFoundException("User not found"));
}
// ***********************************************************
// ******************* FIND USER BY PHONE ********************
// ***********************************************************
@NonNull
@Transactional(readOnly = true)
@Override
public UserResponse getUserByPhoneNumber(String phoneNumber) {
// Phone phone = phoneServiceImpl.getPhoneByNumber(phoneNumber);
// System.out.println(phone);
// UserResponse user = userRepository.getUserByPhone(phone);
// System.out.println(user);
return userRepository.findUserByPhone_Number(phoneNumber);
}
}
and UserController for making requests:
@RequestMapping("/api/v1/users")
public class UserController {
private final UserServiceImpl userService;
private final Logger log = LoggerFactory.getLogger(UserController.class);
@GetMapping(produces = APPLICATION_JSON_VALUE)
public List<UserResponse> getAllUsers() {
log.debug("Getting all users");
return userService.getAllUsers();
@GetMapping(value = "/{userId}", produces = APPLICATION_JSON_VALUE)
public UserResponse getUserById(@PathVariable Long userId) {
return userService.findUserById(userId);
@GetMapping(value = "/phonenumber/{number}", produces = APPLICATION_JSON_VALUE)
public UserResponse getUserByPhoneNumber(@PathVariable String number) {
UserResponse user = userService.getUserByPhoneNumber(number);
System.out.println(user);
<code>@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserServiceImpl userService;
private final Logger log = LoggerFactory.getLogger(UserController.class);
@GetMapping(produces = APPLICATION_JSON_VALUE)
public List<UserResponse> getAllUsers() {
log.debug("Getting all users");
return userService.getAllUsers();
}
@GetMapping(value = "/{userId}", produces = APPLICATION_JSON_VALUE)
public UserResponse getUserById(@PathVariable Long userId) {
return userService.findUserById(userId);
}
@GetMapping(value = "/phonenumber/{number}", produces = APPLICATION_JSON_VALUE)
public UserResponse getUserByPhoneNumber(@PathVariable String number) {
UserResponse user = userService.getUserByPhoneNumber(number);
System.out.println(user);
return user;
}
}
</code>
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserServiceImpl userService;
private final Logger log = LoggerFactory.getLogger(UserController.class);
@GetMapping(produces = APPLICATION_JSON_VALUE)
public List<UserResponse> getAllUsers() {
log.debug("Getting all users");
return userService.getAllUsers();
}
@GetMapping(value = "/{userId}", produces = APPLICATION_JSON_VALUE)
public UserResponse getUserById(@PathVariable Long userId) {
return userService.findUserById(userId);
}
@GetMapping(value = "/phonenumber/{number}", produces = APPLICATION_JSON_VALUE)
public UserResponse getUserByPhoneNumber(@PathVariable String number) {
UserResponse user = userService.getUserByPhoneNumber(number);
System.out.println(user);
return user;
}
}
And I can get list of users, I can get user by ID….. but when I try to get user by phoneNumber (Joined Table), I receive :
"message": "Specified result type [com.app.apringlearn.app.ResponseRequest.UserResponse] did not match Query selection type [com.app.apringlearn.app.Enteties.User] - multiple selections: use Tuple or array"
<code>{
"message": "Specified result type [com.app.apringlearn.app.ResponseRequest.UserResponse] did not match Query selection type [com.app.apringlearn.app.Enteties.User] - multiple selections: use Tuple or array"
}
</code>
{
"message": "Specified result type [com.app.apringlearn.app.ResponseRequest.UserResponse] did not match Query selection type [com.app.apringlearn.app.Enteties.User] - multiple selections: use Tuple or array"
}
then I found that I can not get phones by Id or phonenumber. After how I creted PhoneRepository
which extends JpaRepository<Phone, Long>
and then service and controller
public class PhoneServiceImpl implements PhoneService {
private final PhoneRepository phoneRepository;
@Transactional(readOnly = true)
public PhoneResponse getPhoneByNumber(@NotNull String phoneNumber) {
return phoneRepository.getPhoneByNumber(phoneNumber);
private PhoneResponse buildPhoneResponse(Phone phone) {
return new PhoneResponse().setPhone(phone.getNumber());
@Transactional(readOnly = true)
public PhoneResponse findPhoneById(@NotNull Long phoneId) {
return phoneRepository.findById(phoneId).map(this::buildPhoneResponse).orElseThrow(
()->new EntityNotFoundException("User not found")
@Transactional(readOnly = true)
public List<PhoneResponse> getAllPhone() {
return phoneRepository.findAll().stream().map(this::buildPhoneResponse).collect(Collectors.toList());
<code>@Service
@RequiredArgsConstructor
public class PhoneServiceImpl implements PhoneService {
private final PhoneRepository phoneRepository;
@Override
@Transactional(readOnly = true)
public PhoneResponse getPhoneByNumber(@NotNull String phoneNumber) {
return phoneRepository.getPhoneByNumber(phoneNumber);
}
private PhoneResponse buildPhoneResponse(Phone phone) {
return new PhoneResponse().setPhone(phone.getNumber());
}
@Override
@Transactional(readOnly = true)
public PhoneResponse findPhoneById(@NotNull Long phoneId) {
return phoneRepository.findById(phoneId).map(this::buildPhoneResponse).orElseThrow(
()->new EntityNotFoundException("User not found")
);
}
@Override
@Transactional(readOnly = true)
public List<PhoneResponse> getAllPhone() {
return phoneRepository.findAll().stream().map(this::buildPhoneResponse).collect(Collectors.toList());
}
}
</code>
@Service
@RequiredArgsConstructor
public class PhoneServiceImpl implements PhoneService {
private final PhoneRepository phoneRepository;
@Override
@Transactional(readOnly = true)
public PhoneResponse getPhoneByNumber(@NotNull String phoneNumber) {
return phoneRepository.getPhoneByNumber(phoneNumber);
}
private PhoneResponse buildPhoneResponse(Phone phone) {
return new PhoneResponse().setPhone(phone.getNumber());
}
@Override
@Transactional(readOnly = true)
public PhoneResponse findPhoneById(@NotNull Long phoneId) {
return phoneRepository.findById(phoneId).map(this::buildPhoneResponse).orElseThrow(
()->new EntityNotFoundException("User not found")
);
}
@Override
@Transactional(readOnly = true)
public List<PhoneResponse> getAllPhone() {
return phoneRepository.findAll().stream().map(this::buildPhoneResponse).collect(Collectors.toList());
}
}
and controller:
@RequestMapping("/api/v1/phones")
public class PhoneController {
private final PhoneServiceImpl phoneService;
@GetMapping(produces = APPLICATION_JSON_VALUE)
public List<PhoneResponse> getAllPhones() {
return phoneService.getAllPhone();
@GetMapping(value = "/number/{phoneNumber}", produces = APPLICATION_JSON_VALUE)
public PhoneResponse getPhone(@PathVariable String phoneNumber) {
return phoneService.fetPhoneByNumber(phoneNumber);
@GetMapping(value = "/id/{phoneId}", produces = APPLICATION_JSON_VALUE)
public PhoneResponse getPhoneById(@PathVariable Long phoneId) {
return phoneService.findPhoneById(phoneId);
<code>@RestController
@RequestMapping("/api/v1/phones")
@RequiredArgsConstructor
public class PhoneController {
private final PhoneServiceImpl phoneService;
@GetMapping(produces = APPLICATION_JSON_VALUE)
public List<PhoneResponse> getAllPhones() {
return phoneService.getAllPhone();
}
@GetMapping(value = "/number/{phoneNumber}", produces = APPLICATION_JSON_VALUE)
public PhoneResponse getPhone(@PathVariable String phoneNumber) {
return phoneService.fetPhoneByNumber(phoneNumber);
}
@GetMapping(value = "/id/{phoneId}", produces = APPLICATION_JSON_VALUE)
public PhoneResponse getPhoneById(@PathVariable Long phoneId) {
return phoneService.findPhoneById(phoneId);
}
}
</code>
@RestController
@RequestMapping("/api/v1/phones")
@RequiredArgsConstructor
public class PhoneController {
private final PhoneServiceImpl phoneService;
@GetMapping(produces = APPLICATION_JSON_VALUE)
public List<PhoneResponse> getAllPhones() {
return phoneService.getAllPhone();
}
@GetMapping(value = "/number/{phoneNumber}", produces = APPLICATION_JSON_VALUE)
public PhoneResponse getPhone(@PathVariable String phoneNumber) {
return phoneService.fetPhoneByNumber(phoneNumber);
}
@GetMapping(value = "/id/{phoneId}", produces = APPLICATION_JSON_VALUE)
public PhoneResponse getPhoneById(@PathVariable Long phoneId) {
return phoneService.findPhoneById(phoneId);
}
}
I am able to look for only list of phone numbers. I can not find by Number…I still receive:
"message": "Specified result type [com.app.apringlearn.app.ResponseRequest.UserResponse] did not match Query selection type [com.app.apringlearn.app.Enteties.User] - multiple selections: use Tuple or array"
<code>{
"message": "Specified result type [com.app.apringlearn.app.ResponseRequest.UserResponse] did not match Query selection type [com.app.apringlearn.app.Enteties.User] - multiple selections: use Tuple or array"
}
</code>
{
"message": "Specified result type [com.app.apringlearn.app.ResponseRequest.UserResponse] did not match Query selection type [com.app.apringlearn.app.Enteties.User] - multiple selections: use Tuple or array"
}