Мне нужно определить a для создания экземпляров одного из моих объектов. Это простая задача, и у меня уже есть некоторые, но у этого конкретного объекта есть ссылка на другой объект, который я должен определить в форме. Как это может быть сделано? Я знаю, что могу попросить пользователя ввести идентификатор, сохранить его в DTO и получить реальный объект позже, но я полагаю, что это не лучший способ выполнить это. Что я могу сделать?
Я поставил здесь свои сущности:
@Entity
public class Route {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private Long distance;
@Column(nullable = false)
private String name;
private String description;
@ManyToOne
@JoinColumn
private Place origin;
}
И это объект ссылок:
@Entity
public class Place {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
private Long latitude;
private Long longitude;
private String imagePath;
@OneToMany(mappedBy = "origin", cascade = CascadeType.REMOVE)
private Set<Route> originRoutes;
}
На самом деле это зависит от того, какой вариант использования более подробно. Подумайте о нескольких возможностях:
Создайте место вместе с некоторыми маршрутами мгновенно за один раз - в этом случае я бы реализовал представление так, чтобы он создавал сложную структуру, отражающую объекты один к одному, как вы их определили для JPA, и передает один запрос POST. В основном мы предполагаем, что существует ограниченное количество маршрутов, которые всегда создаются вместе с местами. Маршруты не могут использоваться для разных мест, поскольку это не имеет смысла.
@RequestMapping(method = POST, value = "/places")
public CreatePlaceResponse createPlace(@RequestBody Place place) {
...
}
Создайте место и укажите маршруты в последующих запросах. - если мы хотим большей гибкости и/или ожидаем, что количество маршрутов, назначенных для каждого места, будет большим, мы можем сначала создать "Место", а после этого использовать другой запрос для присвоения ему маршрутов (путем обращения к идентификатору места). Таким образом, вы позволяете пользователю создавать всю структуру шаг за шагом, плюс вы даете возможность добавить Маршрут позже.
@RequestMapping(method = POST, value = "/places")
public CreatePlaceResponse createPlace(@RequestBody Place place) {
...
}
@RequestMapping(method = POST, value = "/places/{placeId}")
public AddRouteResponse addRoute(@RequestBody Route route) {
...
}
В зависимости от случая вы также можете подумать о массовом создании Маршрутов, поэтому передайте список маршрутов в уже созданное место.
На стороне пользовательского интерфейса я вижу, как это работает, используя либо скрытое поле для хранения идентификатора места в ответ на введенный текст, либо как "причудливый" выбор, например один из них ниже, который позволяет вам вводить выбор для фильтрации и выиграть Загрузите 1000 записей в память сразу:
http://silviomoreto.github.io/bootstrap-select/
В любом случае вы собираетесь привязать скрытое поле или выбранную опцию к:
route.place
например
<form:hidden path="place" value="id_of_place_updated_by_javascript" />
или
<form:select path="place">
Затем вы зарегистрируете конвертер, который преобразует переданное значение в требуемый тип, то есть Place. При отправке конвертера вы берете идентификатор места и извлекаете соответствующее место из базы данных. Затем структура свяжет место, возвращаемое конвертером, в Route, поддерживающее форму.
См. Здесь пример использования Formatter для преобразования:
http://springinpractice.com/2012/01/07/making-formselect-work-nicely-using-spring-3-formatters
В последнем примере вы просто отправитесь в базу данных, чтобы получить соответствующий объект вместо создания нового экземпляра.