У меня есть следующий код для приложения Spring Boot:
Сущность:
@Proxy(lazy = false)
public class Vehicle {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String type;
private String make;
private String model;
private Integer year;
Контроллер:
@RequestMapping("/vehicles")
public class VehicleController {
@Autowired
private VehicleService vehicleService;
//GET method to get all vehicles, or specify a parameter
@GetMapping
@ResponseStatus(HttpStatus.OK)
public List<Vehicle> getAllVehicles(
@RequestParam(required = false) Map<String, String> allParams) {
return vehicleService.getVehicles(allParams);
}
Услуга:
private VehicleRepository vehicleRepository;
/**
* Gets the full list of vehicles based on the provided parameters. If no parameters are
* presented, then returns the entire list of vehicles
*
* @param allParams A map of all possible parameters that can be passed through
* @return list of vehicles
*/
@Override
public List<Vehicle> getVehicles(Map<String, String> allParams) {
//gather all of the possible parameters that can be passed through
String type = allParams.get("type");
String make = allParams.get("make");
String model = allParams.get("model");
Integer year;
try {
year = Integer.parseInt(allParams.get("year"));
} catch (NumberFormatException n) {
year = 0;
}
if (type != null && make != null && model != null && year != 0) {
return vehicleRepository.findByTypeAndMakeAndModelAndYear(type, make, model, year);
}
if (make != null && type == null && model != null && year != 0) {
return vehicleRepository.findByMakeAndModelAndYear(make, model, year);
}
if (type != null && make == null && model != null && year != 0) {
return vehicleRepository.findByTypeAndModelAndYear(type, model, year);
}
if (type != null && make != null && model == null && year != 0) {
return vehicleRepository.findByTypeAndMakeAndYear(type, make, year);
}
if (model != null && type == null && make == null && year != 0) {
return vehicleRepository.findByModelAndYear(model, year);
}
if (make != null && type == null && model == null && year != 0) {
return vehicleRepository.findByMakeAndYear(make, year);
}
if (type != null && make == null && model == null && year != 0) {
return vehicleRepository.findByTypeAndYear(type, year);
}
if (type != null && make != null && model != null) {
return vehicleRepository.findByTypeAndMakeAndModel(type, make, model);
}
if (make != null && type == null && model != null) {
return vehicleRepository.findByMakeAndModel(make, model);
}
if (type != null && make == null && model != null) {
return vehicleRepository.findByTypeAndModel(type, model);
}
if (type != null && make != null) {
return vehicleRepository.findByTypeAndMake(type, make);
}
if (type != null) {
return vehicleRepository.findByType(type);
}
if (make != null) {
return vehicleRepository.findByMake(make);
}
if (model != null) {
return vehicleRepository.findByModel(model);
}
if (year != 0) {
return vehicleRepository.findByYear(year);
}
return vehicleRepository.findAll();
}
Репозиторий:
public interface VehicleRepository extends JpaRepository<Vehicle, Long> {
List<Vehicle> findByTypeAndMakeAndModelAndYear(String type, String make, String model,
Integer year);
List<Vehicle> findByMakeAndModelAndYear(String make, String model, Integer year);
List<Vehicle> findByTypeAndModelAndYear(String type, String model, Integer year);
List<Vehicle> findByTypeAndMakeAndYear(String type, String make, Integer year);
List<Vehicle> findByModelAndYear(String model, Integer year);
List<Vehicle> findByMakeAndYear(String make, Integer year);
List<Vehicle> findByTypeAndYear(String type, Integer year);
List<Vehicle> findByTypeAndMakeAndModel(String type, String make, String model);
List<Vehicle> findByMakeAndModel(String make, String model);
List<Vehicle> findByTypeAndModel(String type, String model);
List<Vehicle> findByTypeAndMake(String type, String make);
List<Vehicle> findByType(String type);
List<Vehicle> findByMake(String make);
List<Vehicle> findByModel(String model);
List<Vehicle> findByYear(Integer year);
}
Очевидно, что сервисный уровень имеет много условной логики для покрытия нескольких комбинаций переданных параметров. Хотя это достигает моей цели учета любых пропущенных запросов (например, http://localhost:8080/vehicles?make=&model=&year=&type=
), я хочу выяснить, есть ли способ реорганизовать код, чтобы сделать его более эффективным. Будет ли запрос на примере из Spring достаточным способом решить эту проблему или есть лучший способ? (или этот код настолько хорош, насколько я могу его сделать?)
Рекомендую Spring JPA ExampleMatcher
. Это один из самых простых методов запроса JPA. Вы создаете переменную probe
, которая определяет поиск в базе данных. В запросы включаются только ненулевые значения, для получения дополнительной информации Spring Data JPA Query by Example. Кроме того, я использовал библиотеку Lombok
для аннотации @Data
. Вы можете отказаться от него, если вы не предпочитаете.
Автомобиль.java
@Data
@Entity
@Table
public class Vehicle {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String type;
private String make;
private String model;
private Integer year;
}
VehicleController.java
@RequestMapping("/vehicles")
@RestController
public class VehicleController{
@Autowired
private VehicleService vehicleService;
//GET method to get all vehicles, or specify a parameter
@GetMapping
@ResponseStatus(HttpStatus.OK)
public List<Vehicle> getAllVehicles(
@RequestParam(required = false) Map<String, String> allParams) {
return vehicleService.getVehicles(allParams);
}
}
VehicleRepository.java
public interface VehicleRepository extends JpaRepository<Vehicle, Long> {
}
VehicleService.java
@Service
public class VehicleService {
@Autowired
private VehicleRepository vehicleRepository;
public List<Vehicle> getVehicles(Map<String, String> allParams) {
if (allParams.isEmpty()) {
return vehicleRepository.findAll();
}
Vehicle probe = new Vehicle();
if (allParams.containsKey("type")) {
probe.setType(allParams.get("type"));
}
if (allParams.containsKey("make")) {
probe.setMake(allParams.get("make"));
}
if (allParams.containsKey("year")) {
probe.setYear(Integer.parseInt(allParams.get("year")));
}
if (allParams.containsKey("model")) {
probe.setModel(allParams.get("model"));
}
Example<Vehicle> example = Example.of(probe,
ExampleMatcher.matchingAll()
.withIgnoreCase());
return vehicleRepository.findAll(example);
}
}
Это то, о чем я думал, но я все еще новичок в Spring и не совсем понял эту концепцию. Но я могу подтвердить, что это все еще делает то, что мне нужно! Спасибо!