更新ManyToMany在关联表中添加行 - Spring,Hibernate

时间:2018-03-10 11:10:58

标签: java mysql spring hibernate many-to-many

我正在使用ProductRecipeMenu进行应用。

Product包含idnamecategory列。

@Entity
@Table(name = "products")
public class Product {

    @Id
    @GeneratedValue
    private long id;

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

    @Column(name = "category")
    @Enumerated(EnumType.STRING)
    private Category category;
}

Recipe的ID为name

@Table(name = "recipes")
@Entity
public class Recipe {
    @Id
    @GeneratedValue
    private long id;

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

    @ManyToMany(cascade = CascadeType.DETACH ,fetch = FetchType.EAGER)
    @JoinTable(name = "product2recipe",
            joinColumns = {@JoinColumn(name = "recipe_id")},
            inverseJoinColumns = {@JoinColumn(name = "product_id")})
    private List<Product> products;
}

Menuidname

@Entity
@Table(name = "menus")
public class Menu {
    @Id
    @GeneratedValue
    private long id;

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

    @ManyToMany(cascade = CascadeType.REMOVE,fetch = FetchType.EAGER)
    @JoinTable(name = "recipe2menu",
            joinColumns = {@JoinColumn(name = "menu_id")},
            inverseJoinColumns = {@JoinColumn(name = "recipe_id")})
    private List<Recipe> recipes;
}

我将产品配方与表格product2recipe以及配方菜单与recipe2menu表格相关联。

Recipe可以包含许多Products,而Product可以包含在许多Recipe中,因此它与ManyToMany关系。 Menu包含许多RecipesRecipes可以包含多个Menu,因此它也是ManyToMany关系。

productrecipemenu添加到数据库我正在使用JpaRepository<Product(Recipe/Menu), Long>

我创建了管理Menu的服务:

@Service
public class MenuServiceImpl implements MenuService{

    private MenuRepository menuRepository;
    private RecipeRepository recipeRepository;

    @Override
    public List<Menu> getMenus() {
        return menuRepository.findAll();
    }

    @Override
    public Menu createMenu(String name) {
        Menu menu = new Menu();
        menu.setName(name);
        menu = menuRepository.saveAndFlush(menu);
        return menu;
    }

    @Override
    public Menu getMenu(long id) {
        Menu menu = menuRepository.findById(id).get();
        return menu;
    }

    @Override
    public Menu addRecipe(long menuId, long recipeId) {
        Menu menu = menuRepository.findById(menuId).get();
        Recipe recipe = recipeRepository.findById(recipeId).get();
        List<Recipe> rs = menu.getRecipes();
        rs.add(recipe);
        menu.setRecipes(rs);
        menu = menuRepository.saveAndFlush(menu);
        return menu;
    }
}

并写了测试:

@Test
    public void shouldCreateSingleMenuAndUpdateAddedTheRecipes() {
        Assertions.assertThat(menuRepository.findAll()).size().isEqualTo(0);
        Assertions.assertThat(recipeRepository.findAll()).size().isEqualTo(0);
        Assertions.assertThat(productRepository.findAll()).size().isEqualTo(0);
        Product product = new Product();
        product.setName("rod");
        product.setCategory(Category.FRUIT);
        productRepository.saveAndFlush(product);

        Product product2 = new Product();
        product2.setName("rod2");
        product2.setCategory(Category.NONE);
        productRepository.saveAndFlush(product2);

        Product product3 = new Product();
        product3.setName("rod3");
        product3.setCategory(Category.VEGETABLES);
        productRepository.saveAndFlush(product3);

        Recipe recipe1 = new Recipe();
        recipe1.setName("r1");
        recipe1.addProduct(product);
        recipe1.addProduct(product2);
        recipe1.addProduct(product3);

        recipe1 = recipeRepository.saveAndFlush(recipe1);

        Recipe recipe2 = new Recipe();
        recipe2.setName("r2");
        recipe2.addProduct(product3);

        recipe2 = recipeRepository.saveAndFlush(recipe2);

        Recipe recipe3 = new Recipe();
        recipe3.setName("r3");
        recipe3.addProduct(product3);
        recipe3 = recipeRepository.saveAndFlush(recipe3);

        Menu menu1 = menuService.createMenu("m1");

        menuService.addRecipe(menu1.getId(), recipe1.getId());
        menuService.addRecipe(menu1.getId(), recipe2.getId());

        Menu menu1AfterAddRecipe = menuService.addRecipe(menu1.getId(), recipe3.getId());

        Assertions.assertThat(menu1AfterAddRecipe.getRecipes())
                .extracting("name")
                .containsOnly(recipe1.getName(), recipe2.getName());

        List<Menu> menus = menuRepository.findAll();
        Assertions.assertThat(menus).size().isEqualTo(1);

        Menu actualMenu = menus.get(0);
        Assertions.assertThat(actualMenu).isNotNull();
        Assertions.assertThat(actualMenu.getRecipes()).size().isEqualTo(2);
        Assertions.assertThat(actualMenu.getRecipes())
                .extracting("name")
                .containsOnly(recipe1.getName(), recipe2.getName());
    } 

当我menuService.addRecipe(menu1.getId(), recipe2.getId());第一次第二次在表recipe2menu中进行时,会有单行(recipe_i - menu_id)。但是第二次我有3排(1-1; 1-1; 1-2)。但我只想到2,因为我只增加了两次。当我再次调用menuService.addRecipe(menu1.getId(), recipe2.getId());时,行将为6(1-1; 1-1; 1-1; 1-1; 1-2; 1-3)。如果我没有将产品添加到配方中,问题就会消失......每次添加单个配方时,配方中的产品越多,recipe2menu表中的行就越多。

Menu menu1AfterAddRecipe = menuService.addRecipe(menu1.getId(), recipe3.getId());处的断点: enter image description here

我正在使用MySql。

有什么想法吗?

非常感谢您的帮助!

0 个答案:

没有答案