Tengo dos entidades, Meal
y Mealplan
en una relación @ManyToMany. Cada Mealplan consta de cinco objetos comida.
Comida:
@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;
}
Régimen de comidas:
public class Mealplan {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private int calendarweek;
@ManyToMany
private List<Meal> mealsPerWeek;
El JSON de, por ejemplo, /mealplan/1
es similar al siguiente:
{
id: 1,
calendarweek: 10,
mealsPerWeek: [
{
id: 4,
name: "Linsensuppe",
price: 23.5,
art: "vegan"
},
{
id: 3,
name: "Salat",
price: 3,
art: "vegetarisch"
},
Ahora quiero crear un método (personalizado?) Para agregar una comida en un Mealplan. ¿Cuál es la mejor manera de hacerlo? Estaba pensando en un método personalizado en mi repositorio de esta manera:
@RestController
@RequestMapping("/mealplan")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class MealplanController {
@PostMapping
public void addMealToMealplan(@RequestBody Meal meal) {
mealplanRepository.addMealToMealplan(essen);
}
Pero, ¿cómo puedo añadir este método personalizado en el repositorio? ¿Cómo funciona un método performant para este parece?
@Repository
public interface MealplanRepository extends JpaRepository<Mealplan, Integer> {
void addMealToMealplan(Meal meal);
}
No funciona, por ejemplo, además de que no se puede declarar un método en una interfaz. ¿Necesito una nueva clase para eso?
Me gustaría ir con algo como esto:
Para asegurarse de crear la interfaz JPA MealRepository
@Repository
public interface MealRepository extends JpaRepository<Meal, Integer> {
}
a continuación, crear preferiblemente MealPlanService para manejar cualquier operación en objetos (no hacer el trabajo real en el controlador), la inyección de ambos repositorios. Y cada vez que estamos añadiendo nueva comida que persisten en primer lugar, y luego añadimos a colleciton de comidas en el objeto mealplan. Transaccional para actualizar automáticamente planes de alimentos (se puede invocar de forma manual a ahorrar en mealplan)
@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;
}
}
Y en el controlador de Autowire servicio y ejecutar. Eso está muy bien de ello se puede, además, asegurar y gracia coger si alguien trata de alterar mealplan no existir, o no su (con cierta lógica adicional en servicio)
@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();
}
}
Solicitud POST en /mealplan/1/add
con el cuerpo de la nueva comida (donde 1 es el mealPlanId
al que hay que añadir las comidas).
Controlador llamará Servicio que tratará de primer hallazgo mealplan basado en Identificación del pasado _mealPlanRepository.findById(mealPlanId)
Esto devolverá opcional y encadenar funcionamiento de geting valor llamando _mealPlanRepository.findById(mealPlanId).orElseThrow(MealNotFoundException::new)
Por entidad dimos cuenta de que a continuación, añadimos nuestra nueva comida (se persistió debido a la transaccional, pero se puede invocar _mealPlanRepository.save()
en él en lugar de
Si todo se hace corectly, Retus servicio actualiza entidad, y el controlador vuelve entonces Respuesta entidad con mealplan actualizado