使用@ManyToOne 如何将我的一个用户映射到汽车?

Using @ManyToOne how to map my one User to Cars?

我正在尝试在用户添加优惠时将所有者(用户)映射到优惠(汽车)。使用如下设置 user_id 始终为空。我错过了什么?我认为这与控制器有关。映射对我来说似乎没问题,但我可能错了。 Owner是登录并添加offer的人,所以应该由他的id映射。

编辑 我发现我的@AuthenticationPrincipal Authentication auth 始终为 null,即使只有经过身份验证的用户才能访问 POST /api/cars 端点。这似乎违反直觉

车载控制器

    @Controller
    public class CarController {

    @Autowired
    private CarService carService;
    
    
    @Autowired
    UserRepository userRepository;
    
    @GetMapping("/api/cars")
    public String getCars(Model model) {
        model.addAttribute("cars", carService.getAllCars());
        return "cars";
    }
    
    @GetMapping("/api/cars/new")
    public String createNewCarOfferForm(Model model) {
        Car car = new Car();
        model.addAttribute("car", car);
        return "createNewOfferForm";
    }
    
    @PostMapping("/api/cars")
    public String saveCar(@ModelAttribute("car") Car car, @AuthenticationPrincipal Authentication auth) {
        User customUser = (User)auth;
        car.setOwner(customUser);
        carService.saveCar(car);
        return "redirect:/api/cars";
    }
    
    @GetMapping("/api/cars/view/{id}")
    public String viewOffer(@PathVariable Long id, Model model) {
        model.addAttribute("car", carService.getCarById(id));
        return "viewOffer";
    }
    
     }

用户实体

@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String roles = "ROLE_USER";

@OneToMany(mappedBy = "owner")
private Set<Car> cars = new HashSet<>();

public User() {
    super();
}

public User(String username, String password, String roles) {
    super();
    this.username = username;
    this.password = password;
    this.roles = roles;
//GETTERS SETTERS

汽车实体

@Entity
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String carPhotoUrl;
private String carTitle;
private double price;
private int yearModel;
private int mileage;
private String engineType;
private float engineCapacity;
private int enginePower;
private String gearboxType;
private String driveType;
private String colour;
private Boolean isDamaged;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="user_id", referencedColumnName = "id")
private User owner;

public Car() {
    super();
}

public Car(String carPhotoUrl, String carTitle, double price, int yearModel, int mileage, String engineType,
        float engineCapacity, int enginePower, String gearboxType, String driveType, String colour,
        Boolean isDamaged) {
    super();
    this.carPhotoUrl = carPhotoUrl;
    this.carTitle = carTitle;
    this.price = price;
    this.yearModel = yearModel;
    this.mileage = mileage;
    this.engineType = engineType;
    this.engineCapacity = engineCapacity;
    this.enginePower = enginePower;
    this.gearboxType = gearboxType;
    this.driveType = driveType;
    this.colour = colour;
    this.isDamaged = isDamaged;
}

 //GETTERS SETTERS

用户存储库

public interface UserRepository extends JpaRepository<User, Long> 
{

Optional<User> findByUsername(String username);

Optional<User> findById(Long id);
}

用户详情服务

public class UserDetailsService implements UserDetails{

private String username;
private String password;
private List<GrantedAuthority> authorities;

public UserDetailsService() {
    super();
}

public UserDetailsService(User user){
    this.username=user.getUsername();
    this.password=user.getPassword();
    this.authorities = Arrays.stream(user.getRoles().split(","))
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList()); 
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return authorities;
}

@Override
public String getPassword() {
    return password;
}

@Override
public String getUsername() {
    return username;
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    return true;
}

我认为您需要在所有者中提及级联类型“cascade=CascadeType.ALL”,这实际上意味着用户(所有者)发生的任何更改也必须级联到汽车。

如果我们保存一个用户(所有者),那么所有关联的汽车也将被保存到数据库中。如果您删除一个用户(所有者),那么与该用户(所有者)关联的所有汽车也将被删除。足够简单!

我修好了,但花了我一些时间。 现在这是添加汽车的端点(因此没有@AuthenticationPrincipal)

@PostMapping("/api/cars/addCar")
    public String saveCar(@ModelAttribute("car") Car car, Principal 
    principal) {
        User user = userService.getUserByName(principal.getName());
        car.setOwner(user);
        carService.saveCar(car);
        return "redirect:/api/cars";
    }

我敢打赌这不是一个干净的解决方案。我已将 return 类型的 UserRepository 从可选更改为用户。我认为这将在未来带来更多问题。但目前它有效。