Я уже давно пытаюсь решить эту проблему, но я никуда не попал. Я пытался сохранить сущность, которая имеет ссылку на другую сущность.
Пользователь создает объект размещения, заполнив форму, а затем нажимает сохранить, чтобы сохранить ее. Он должен автоматически создавать новые строки в таблицах ' place ' и ' place_urls '. Вот ссылка на файл SQL, который я загружаю в приложение: https://pastebin.com/x8Gvk7ub
Родительский объект:
@Entity
@Table(name="places")
public class Place {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id", nullable=false, updatable=false)
private Long id;
@Column(name="userId")
private Long userId;
@Column(name="name", nullable=false, unique=true)
private String name;
@Column(name="address", nullable=false)
private String address;
@Column(name="largeDescription", nullable=false)
private String largeDescription;
@Column(name="smallDescription", nullable=false)
private String smallDescription;
@OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinColumn(name="id")
private PlaceUrl placeUrl;
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinColumn(name="id")
private List<Booking> bookings;
getters and setters...
}
Дочерний объект:
@Entity
@Table(name="placeUrls")
public class PlaceUrl {
@Id
@Column(name="id", nullable=false, updatable=false)
private Long id;
@Column(name="placeId", nullable=false, updatable=false)
private Long placeId;
@Column(name="url", nullable=false, updatable=true, unique=true)
private String url;
@OneToOne
@JoinColumn(name="id", referencedColumnName="placeId")
private Place place;
getters and setters...
}
Контроллер:
@PostMapping("/place/add")
public String addPlace(@ModelAttribute Place place, @AuthenticationPrincipal UserDetails currentUser) {
User user = userRepository.findUserByUsername(currentUser.getUsername());
place.setUserId(user.getId());
placeRepository.save(place);
return "redirect:/places";
}
Именование Hibernate установлено в implicitic-strategy
в application.properties
ОБНОВЛЕНИЕ :
Место объекта:
@OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="place")
private PlaceUrl placeUrl;
Объект PlaceUrl:
Removed the placeId column, placeId variable and it's getters and setters.
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="placeId")
private Place place;
Изменения контроллера:
@PostMapping("/place/add")
public String addPlace(@ModelAttribute Place place, @AuthenticationPrincipal UserDetails currentUser) {
User user = userRepository.findUserByUsername(currentUser.getUsername());
place.setUserId(user.getId());
place.getPlaceUrl().setUrl("something_nice");
placeRepository.save(place);
return "redirect:/places";
}
Теперь при сохранении я получаю: No message available java.lang.NullPointerException
ОБНОВЛЕНИЕ 2 :
Я начал работать, просто бездельничая. Я понятия не имею, почему это работает, поэтому кто-то другой может объяснить.
@PostMapping("/place/add")
public String addPlace(Model model, @ModelAttribute Place place, @AuthenticationPrincipal UserDetails currentUser) {
PlaceUrl placeUrl = new PlaceUrl();
User user = userRepository.findUserByUsername(currentUser.getUsername());
placeUrl.setUrl(place.getName());
place.setPlaceUrl(placeUrl);
place.setUserId(user.getId());
placeUrl.setPlace(place); <-- this line here made it all work
placeRepository.save(place);
return "redirect:/places";
}
Я следовал инструкциям руководства, которое мне предложили. По сути, я добавил @OneToOne (mappedBy = "place") к родителю, затем добавил @OneToOne и @JoinColumn (name = "placeId") к дочерней сущности.