I'm doing a vote counting system, the winner is the one who has more than 3 votes, however, I'm facing the following problem. When there is more than one place with 3 votes, instead of my JSON returning the one with the most votes, it always returns the one with more than 3 votes ordered by ID. That is, if the restaurant with ID 1 has 3 votes, and the restaurant with ID 2 has 10 votes, the restaurant with ID 1 ends up appearing on the route /restaurants/winner despite not being the most voted, is there any way I can make the most voted show up?
e.g: return from /restaurants/winner route
{
"id": 1,
"restaurant": "Burger King",
"address": "Av. Ipiranga, 1600",
"website": "https://www.burgerking.com.br/",
"description": "Rede de fast-food famosa com hambúrgueres grelhados, batata frita e milk-shakes.",
"count": 3
}
While McDonalds has 5 votes
{
"id": 2,
"restaurant": "McDonalds",
"address": "Av. Ipiranga, 5200",
"website": "https://www.mcdonalds.com.br/",
"description": "Rede de fast-food tradicional conhecida por ter ótimos hambúrgueres e batatas fritas.",
"count": 5
}
Here are the classes that I'm using:
Restaurant.java
package com.dbserver.restaurantes.entities;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name = "db_restaurants")
public class Restaurant {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String restaurant;
private String address;
private String website;
private String description;
private Integer count;
@JsonIgnore
@OneToMany(mappedBy = "id.restaurant")
private Set<Vote> votes = new HashSet<>();
public Restaurant() {
}
public Restaurant(Long id, String restaurant, String address, String website, String description, Integer count) {
this.id = id;
this.restaurant = restaurant;
this.address = address;
this.website = website;
this.description = description;
this.count = count;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRestaurant() {
return restaurant;
}
public void setRestaurant(String restaurant) {
this.restaurant = restaurant;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Set<Vote> getVotes() {
return votes;
}
}
RestaurantDTO.java
package com.dbserver.restaurantes.dto;
import com.dbserver.restaurantes.entities.Restaurant;
public class RestaurantDTO {
private Long id;
private String restaurant;
private String address;
private String website;
private String description;
private Integer count;
public RestaurantDTO() {
}
public RestaurantDTO(Long id, String restaurant, String address, String website, String description, Integer count) {
this.id = id;
this.restaurant = restaurant;
this.address = address;
this.website = website;
this.description = description;
this.count = count;
}
public RestaurantDTO(Restaurant restaurantDTO) {
id = restaurantDTO.getId();
restaurant = restaurantDTO.getRestaurant();
address = restaurantDTO.getAddress();
website = restaurantDTO.getWebsite();
description = restaurantDTO.getDescription();
count = restaurantDTO.getCount();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRestaurant() {
return restaurant;
}
public void setRestaurant(String restaurant) {
this.restaurant = restaurant;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
RestaurantServices.java
package com.dbserver.restaurantes.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.dbserver.restaurantes.dto.RestaurantDTO;
import com.dbserver.restaurantes.entities.Restaurant;
import com.dbserver.restaurantes.exceptions.NotFoundException;
import com.dbserver.restaurantes.repositories.RestaurantRepository;
@Service
public class RestaurantServices {
@Autowired
private RestaurantRepository repository;
@Transactional(readOnly = true)
public Page<RestaurantDTO> findAll(Pageable pageable) {
Page<Restaurant> result = repository.findAll(pageable);
Page<RestaurantDTO> page = result.map(x -> new RestaurantDTO(x));
return page;
}
@Transactional(readOnly = true)
public RestaurantDTO findById(Long id) {
Restaurant result = repository.findById(id).get();
RestaurantDTO dto = new RestaurantDTO(result);
return dto;
}
@Transactional(readOnly = true)
public Restaurant findWinner(Integer count) {
List<Restaurant> restaurants = repository.findAll();
for (Restaurant restaurant : restaurants) {
// Hibernate.initialize(restaurant.getCount());
if (restaurant.getCount() >= 3) {
return restaurant;
}
}
throw new NotFoundException(
"Nenhum restaurante ganhou a votação, é necessário um total de 3 votos para ter um restaurante vencedor.");
}
@Transactional
public Restaurant addRestaurant(Restaurant newRestaurant) {
return repository.saveAndFlush(newRestaurant);
}
}
RestaurantRepository.java
package com.dbserver.restaurantes.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import com.dbserver.restaurantes.entities.Restaurant;
public interface RestaurantRepository extends JpaRepository<Restaurant, Long> {
}
RestaurantController.java
package com.dbserver.restaurantes.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.dbserver.restaurantes.dto.RestaurantDTO;
import com.dbserver.restaurantes.entities.Restaurant;
import com.dbserver.restaurantes.services.RestaurantServices;
@RestController
@RequestMapping(value = "/restaurants")
public class RestaurantController {
@Autowired
private RestaurantServices service;
@GetMapping
public Page<RestaurantDTO> findAll(Pageable pageable) {
return service.findAll(pageable);
}
@GetMapping(value = "/{id}")
public RestaurantDTO findById(@PathVariable Long id) {
return service.findById(id);
}
@GetMapping(value = "/winner")
public Restaurant findWinner(Integer count) {
return service.findWinner(count);
};
@PostMapping
public Restaurant addRestaurant(@RequestBody Restaurant newRestaurant) {
return service.addRestaurant(newRestaurant);
}
}
CodePudding user response:
You have to check the top value as well. So You need to add your own query for that. Here is the code
public interface RestaurantRepository extends JpaRepository<Restaurant, Long>
{
Optional<Restaurant> findFirstByCountGreaterThanEqualOrderByCountDesc (Integer count);
}
and Use that inside your method
@Transactional(readOnly = true)
public Restaurant findWinner(Integer count) throws NotFoundException
{
Optional<Restaurant> data = repository.findFirstByCountGreaterThanEqualOrderByCountDesc(3);
if (data.isPresent())
{
return data.get();
}
throw new NotFoundException("Nenhum restaurante ganhou a votação, é necessário um total de 3 votos para ter um restaurante vencedor.");
}
You can use native queries as well.