Home > Software engineering >  Spring JPA: Adding an entity with current user ID as foreign key
Spring JPA: Adding an entity with current user ID as foreign key

Time:11-29

I'm using a Thymeleaf HTML registration form and simple save/update method to save/update a 'dish' object to a mySQL database. Restaurant Id is a foreign key for the 'dish' but using the below methods it saves as 'null',

I would like to make it so that the Restaurant id of the currently logged in restaurant owner saves automatically when they add a dish.

Is there an uncomplicated way to do this? The closest tutorial I've found on Youtube involves using JSON requests in Postman and I've had issue adapting that to a HTML registration form in the past.

I'm quite new to all of this so any help would be very much appreciated!

See Dish class:

package com.bron.demoJPA.appuser;
    
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString(exclude = "reqlist")
public class Dish {

    @Id
    @SequenceGenerator(name = "dish_sequence", sequenceName = "dish_sequence", allocationSize = 1)

    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dish_sequence")
    @Column(name = "dish_Id")
    private Long dishId;

    @Column(name = "dish_name")
    private String dname;

    @Column(name = "dish_description")
    private String description;

    @Column(name = "dish_price")
    private double price;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "Rest_ID", referencedColumnName = "Rest_ID")
    private AppUser app;

    @ManyToMany(cascade = CascadeType.ALL)

    @JoinTable(name = "dish_requirment_mapping", joinColumns = @JoinColumn(name = "dish_Id", referencedColumnName = "dish_Id"), inverseJoinColumns = @JoinColumn(name = "Require_ID", referencedColumnName = "Require_ID"))
    private List<Requirments> reqlist;

    public void addRequirments(Requirments req) {
        if (reqlist == null)
            reqlist = new ArrayList<>();
        reqlist.add(req);

    }
}

See AppUser(restaurant owner) Class

    @Column(name = "Rest_Password")
    private String password;

    @Column(name = "Rest_Email_Address")
    private String email;

    @Enumerated(EnumType.STRING)
    private AppUserRole appUserRole;
    private Boolean locked = false;
    // don't enable user until email verification
    private Boolean enabled = false;

    public AppUser(String restname, String email, String pass, AppUserRole app) {
        this.restaurantName = restname;
        this.email = email;
        this.password = pass;
        this.appUserRole = app;
    }

    public Collection<? extends GrantedAuthority> getAuthorities() {
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(appUserRole.name());
        return Collections.singletonList(authority);
    }

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

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

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

    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }

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

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

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)

    @JoinColumn(name = "openingHourID", referencedColumnName = "OpeningHour_ID")
    private OpeningHour opening;
}

See Controller class:

package com.bron.demoJPA.conroller;
@Controller
public class DishController {
//display list of employees
    @Autowired
    private DishService dishService;

    @GetMapping("/dish")
    public String viewHomePage(Model model) {
        model.addAttribute("listDish", dishService.getAllDish());
        return "index";
    }

    @GetMapping("/showNewDishForm")
    public String showNewDishForm(Model model) {
        // Create model attribute to bind form data
        Dish dish = new Dish();
        model.addAttribute("dish", dish);
        return "new_dish";
    }

    @PostMapping("/saveDish")
    public String saveDish(@ModelAttribute("dish") Dish dish) {
        // save dish to database
        dishService.saveDish(dish);
        return "redirect:/dish";
    }



@GetMapping("/showFormForUpdate/{dishId}")
    public String showFormForUpdate(@PathVariable(value = "dishId") long dishId, Model model) {
        // get dish from service
        Dish dish = dishService.getDishByDishId(dishId);

        // set dish as model to pre-populate the form data
        model.addAttribute("dish", dish);
        return "update_dish";

    }

}

See Service implementation

package com.bron.demoJPA.service;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bron.demoJPA.appuser.Dish;
import com.bron.demoJPA.repository.DishRepository;

@Service
public class DishServiceImpl implements DishService {

    @Autowired
    private DishRepository dishRepository;

    @Override
    public List<Dish> getAllDish() {
        return dishRepository.findAll();
    }

    @Override
    public void saveDish(Dish dish) {
        this.dishRepository.save(dish);
    }

    @Override
    public Dish getDishByDishId(long dishId) {
        Optional<Dish> optional = dishRepository.findById(dishId);
        Dish dish = null;
        if (optional.isPresent()) {
            dish = optional.get();
        } else {
            throw new RuntimeException("Dish not found for: "   dishId);
        }
        return dish;
    }
}

See Service class

public interface DishService {

    List<Dish> getAllDish();

    void saveDish(Dish dish);

    Dish getDishByDishId(long dishId);

}

CodePudding user response:

Can you make sure Dish's "app" attribute is being set correctly before trying to save it?

If it's null or it's a brand new instance of AppUser class it makes sense that when trying to match and persist it ends up on null.

Greetings!

  • Related