Допустим, у меня есть таблица postgres с именем Employee со следующими столбцами:
Мне интересно иметь конечную точку REST, чтобы /employee/{ID} вернул всю информацию для этого конкретного сотрудника в формате JSON, но если я укажу /employee/{ID}/FirstName, то он вернет имя конкретного сотрудника только в формате JSON, /employee/{ID}/LastName вернет фамилию сотрудника в формате JSON. формат JSON и так далее. Есть ли хороший способ реализовать это вместо реализации конечной точки для доступа к каждому столбцу? Спасибо.
Я считаю, что это решение, которое я ищу. Но означает ли это также, что в моей функции конечной точки мне потребуется функция сопоставления, которая переходит от атрибута к извлечению столбцов? Я думаю, мой главный вопрос в том, что сейчас в базе данных 7 столбцов, и я могу определить их, как вы упомянули, но если в будущем будет добавлен 8-й столбец, возможно ли, что мы можем создать конечную точку теперь, чтобы нам не нужно было изменять код при добавлении нового столбца?
Когда я использую {attribute} в конечной точке, это подстановочный знак, который обычно реализуется с помощью PathVariable (или его эквивалента). Убедитесь, что любая библиотека, которую вы используете для REST/MVC, поддерживает это. Если это так, вам нужно будет написать свое сопоставление. Сопоставление нужно будет изменить, если вы добавите новый столбец, но ваша конечная точка этого не сделает.
Спасибо. Я считаю, что «сопоставление нужно будет изменить, если вы добавите новый столбец», это то, что я действительно хотел проверить.




Простой способ решить эту проблему — использовать параметр запроса вместо запроса URL-адреса. Используя такой параметр, как fields, вы получите URL-адрес, подобный /employee/{id}?fields=FirstName,LastName. Используя приведенный ниже код, вы можете получить Map<String, Object>, который будет сериализован в JSON с вашими данными. Нравится:
@ResponseBody
public Map<String, Object> getPerson(@PathVariable("id") long id, @RequestParam("fields") String fields) throws Exception {
return personService.getPersonFields(id, fields);
}
@Service
class PersonService {
public Map<String, Object> getPersonFields(Long personId, String fields) throws Exception {
final Person person = personRepository.findById(personId);
if (person == null) {
throw new Exception("Person does not exists!");
}
String[] fieldsArray = fields.split(",");
Map<String, Field> personFields = Arrays.stream(person.getClass().getFields()).collect(Collectors.toMap(Field::getName, field -> field);
Map<String, Object> personFieldsReturn = new HashMap<>();
for (String field : fieldsArray) {
if (personFields.containsKey(field)) {
personFields.get(field).setAccessible(true);
personFieldsReturn.put(field, personFields.get(field).get(person));
personFields.get(field).setAccessible(false);
}
}
return personFieldsReturn;
}
}
Однако это не очень хорошее решение. Но это должно работать.
Это рискованное решение — вам лучше не раскрывать имена столбцов в вашем API.
Что ж, используйте его для сопоставления вашего DTO с контроллером вместо сопоставления сущности со службой. Это та же логика.
Таким образом, вы можете определить абстрактный контроллер и централизовать логику сопоставления полей всех DTO. Вы понимаете мою точку зрения?
Я вижу вашу точку зрения. Однако столбцы (или поля) базы данных относятся к уровню доступа к данным и не должны отображаться в контроллерах. Любое сопоставление атрибутов объекта (часть модели) с концепциями БД относится к уровню доступа к данным.
Итак, как упоминал @dave в комментарии, у вас может быть конечная точка REST /employee/{ID}/{column}, и в вашем контроллере у вас будет сопоставление между значением аргумента {column} и фактическим именем столбца в базе данных. Если вы не хотите повторно развертывать свое приложение при изменении сопоставления, вы можете поместить его в отдельный файл свойств на сервере за пределами вашего jar/war, а также добавить дополнительную конечную точку либо для перезагрузки файла формы сопоставления на сервере, либо для конечной точки. что позволит загружать и анализировать файл с сопоставлением непосредственно с вашим приложением.
Я бы посоветовал вам использовать RepositoryRestResource из Spring Data.
Прежде всего, создайте свою сущность:
public class Employee {
//props
}
После этого создайте Employee Repository:
@RepositoryRestResource(collectionResourceRel = "employee", path = "employee")
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {
List<Employee> findByLastName(@Param("firstName") String firstName);
}
И все, вы получите:
и так далее.
Ознакомьтесь с документами:
Не могли бы вы сделать это с одной конечной точкой, т.е.
/employee/{id}/{attribute}и сопоставитьattributeс именем столбца?