春季:如何将请求发布到多对多关系中

时间:2020-03-18 13:50:21

标签: java spring jpa spring-data-jpa

我在@ManyToMany关系中有两个实体MealMealplan。每个Mealplan包含五个Meal对象。

用餐:

@Entity
public class Meal {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private BigDecimal price;
    private String type;

    @ManyToMany(mappedBy = "mealsPerWeek")
    private List<Mealplan> mealplan;
}

用餐计划:

public class Mealplan {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private int calendarweek;

    @ManyToMany
    private List<Meal> mealsPerWeek;

例如/mealplan/1的JSON如下所示:

{
id: 1,
calendarweek: 10,
mealsPerWeek: [
   {
   id: 4,
   name: "Linsensuppe",
   price: 23.5,
   art: "vegan"
   },
   {
   id: 3,
   name: "Salat",
   price: 3,
   art: "vegetarisch"
   },

现在,我想创建(自定义?)方法以将餐添加到Mealplan中。最好的方法是什么?我在考虑这样的自定义方法:

@RestController
@RequestMapping("/mealplan")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class MealplanController {

    @PostMapping
    public void addMealToMealplan(@RequestBody Meal meal) {
        mealplanRepository.addMealToMealplan(essen);
    }

但是如何将这个自定义方法添加到存储库中?这种方法的效果如何?

@Repository
public interface MealplanRepository extends JpaRepository<Mealplan, Integer> {

 void addMealToMealplan(Meal meal);
}

例如不起作用,而且我无法在接口中声明方法。我需要一个新的班级吗?

1 个答案:

答案 0 :(得分:1)

我会选择这样的东西:

确保创建MealRepository jpa接口

@Repository
public interface MealRepository extends JpaRepository<Meal, Integer> {
}

然后最好创建MealPlanService来处理对对象的任何操作(不要在控制器中进行实际工作),同时注入两个存储库。每当我们添加新餐时,我们都将其持久保存,然后将其添加到餐计划对象的餐中。事务性以自动更新膳食计划(您可以手动调用保存膳食计划)

@Service
public class MealPlanService{
    private MealRepository  _mealRepository;
    private MealPlanRepository _mealPlanRepository;

    @Autowire
    MealPlanService(MealRepository mealRepository,MealPlanRepository mealPlanRepository)
      _mealRepository = mealRepository
      _mealPlanRepository = mealPlanRepository
    }

    @Transactional
    public Mealplan addMealToMealplan(int mealPlanId, Meal meal) throws MealNotFoundException{
          Mealplan mealplan = _mealPlanRepository.findById(mealPlanId).orElseThrow(MealNotFoundException::new)
          meal = _mealRepository.save(meal); 
          mealplan.getMealsPerWeek().add(meal)
          return mealplan;
    }
}

然后在Controller autowire服务中执行。不错的东西,如果有人尝试更改不存在的就餐计划或不更改其就餐计划,您还可以安全并优雅地捕获(使用某些额外逻辑)

@RestController
@RequestMapping("/mealplan")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class MealplanController {
    private MealPlanService _mealPlanService;

    @Autowire
    MealplanController (MealPlanService mealPlanService){
            _mealPlanService = mealPlanService;
    }

    @PostMapping(path = "/{mealPlanId}/add")
    public ResponseEntity<MealPlan> addMealToMealplan(@PathVariable int mealPlanId , @RequestBody Meal meal) {
            try{
                 return ResponseEntity.ok(_mealPlanService.addMealToMealplan(meal));
            catch (MealNotFoundException e){
                 //do some other logic, return error , log it or smth
                 ResponseEntity.notFound().build();
            }
    } 

/mealplan/1/add上发布带有新餐的邮件(其中1是您的mealPlanId,应添加餐)。

控制器将呼叫服务服务,该服务将尝试首先根据传递的ID _mealPlanRepository.findById(mealPlanId)

查找进餐计划

这将返回Optional,我们通过调用_mealPlanRepository.findById(mealPlanId).orElseThrow(MealNotFoundException::new)

链接获取价值的操作

然后在找到的实体上添加新餐(由于Transactional,它将继续存在,但是您可以在其上调用_mealPlanRepository.save()而不是

如果一切都已完成,则服务将更新实体,然后控制器将返回带有更新膳食计划的Response实体