I've been trying to solve this thing for along time now, but I haven't gotten anywhere. I've been trying to save a entity that posses a reference to another entity.
User creates an place entity by filling out the form then presses save to save it. It should automatically make new rows into 'places' and 'place_urls' tables. Here is a link to SQL file that I'm loading into the application: https://pastebin.com/x8Gvk7ub
Parent entity:
@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...
}
Child entity:
@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...
}
Controller:
@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 naming is set to implicitic-strategy
in application.properties
UPDATE:
Place entity:
@OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="place")
private PlaceUrl placeUrl;
PlaceUrl entity:
Removed the placeId column, placeId variable and it's getters and setters.
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="placeId")
private Place place;
Controller changes:
@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";
}
Now upon save I get: No message available java.lang.NullPointerException
UPDATE 2:
I got working by just messing around. I have no idea why it works, so someone else can explain.
@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";
}
I followed the instructions of the guide book that I was suggested. Basically I added @OneToOne(mappedBy="place") to the parent then I added @OneToOne and @JoinColumn(name="placeId") to the child entity.