"отделенная сущность передана для сохранения" Когда я пытаюсь сохранить сущность с отношением ManyToMany - PullRequest
0 голосов
/ 05 мая 2020

Я знаю, что есть много похожих вопросов, но я не встречал ни одного с решением моей проблемы, и я уже перепробовал все, что мог - и я прочитал.

Итак, проблема в основном в том, что Я не могу сохранить в своем коде экземпляр сущности «Рецепт» с отношениями ManyToMany с другой «категорией» в моей базе данных h2 без сохранения экземпляра категории до этого в потоке кода.

This " Сущность "рецепт" уже содержит в своем объявлении множество других сущностей (примечания - OneToOne, Ingredient OneToMany), и все работает безупречно, без сохранения их ранее.

categoryRepository.save(newCategory);
recipeRepository.save(perfectGuacamole);

Итак, этот код работает отлично, но я хотел бы Избегайте сохранения перед категорией, как я уже делал для других сущностей. Таким образом, в основном даже без сохранения оставшихся сущностей (ингредиентов, примечаний) этот код неявно сохраняет их.

Код:

    Category american = categoryRepository.findByDescription("American").get();
    Category mexican = categoryRepository.findByDescription("Mexican").get();


    Recipe perfectGuacamole = new Recipe();
    Set<Recipe> newCategoryRecipes = new HashSet<>();
    newCategoryRecipes.add(perfectGuacamole);

    // CREATING A NEW CATEGORY
    Category newCategory = new Category();
    newCategory.setDescription("New");
    newCategory.setRecipes(newCategoryRecipes);

    // CRIATING A NEW SET OF GUACAMOLE'S CATEGORIES
    Set<Category> categories = new HashSet<>();
    categories.add(newCategory);
    categories.add(american);
    categories.add(mexican);


    // CREATING GUACAMOLE'S NOTES
    Notes notes = new Notes();
    notes.setRecipe(perfectGuacamole);
    notes.setRecipeNotes("Be careful handling chiles if using. Wash your hands thoroughly after handling and do not touch your eyes or the area near your eyes with your hands for several hours.");

    // CRIATING GUACAMOLE'S INGREDIENT'S
    Set<Ingredient> ingredientesGuacamole = new HashSet<>();
    Ingredient avocado = new Ingredient("Avocado", new BigDecimal(2), unitOfMeasureRepository.findByDescription("Unit").get(), perfectGuacamole);
    Ingredient salt = new Ingredient("Salt", new BigDecimal(0.25), unitOfMeasureRepository.findByDescription("Teaspoon").get(), perfectGuacamole);
    Ingredient lemonJuice = new Ingredient("Lemon juice", new BigDecimal(0.25), unitOfMeasureRepository.findByDescription("Tablespoon").get(), perfectGuacamole);

    ingredientesGuacamole.add(avocado);
    ingredientesGuacamole.add(salt);
    ingredientesGuacamole.add(lemonJuice);
    perfectGuacamole.setCookTime(10);
    perfectGuacamole.setDifficulty(Difficulty.MODERATE);
    perfectGuacamole.setDescription("The best guacamole keeps it simple: just ripe avocados, salt, a squeeze of lime, onions, chiles, cilantro, and some chopped tomato. Serve it as a dip at your next party or spoon it on top of tacos for an easy dinner upgrade.");
    perfectGuacamole.setCategories(categories);
    perfectGuacamole.setUrl("https://www.simplyrecipes.com/recipes/perfect_guacamole/");
    perfectGuacamole.setDirections("1 Cut the avocado, remove flesh: Cut the avocados in half. Remove the pit. Score the inside of the avocado with a blunt knife and scoop out the flesh with a spoon. (See How to Cut and Peel an Avocado.) Place in a bowl.\n" +
            "2 Mash with a fork: Using a fork, roughly mash the avocado. (Don't overdo it! The guacamole should be a little chunky.)\n" +
            "3 Add salt, lime juice, and the rest: Sprinkle with salt and lime (or lemon) juice. The acid in the lime juice will provide some balance to the richness of the avocado and will help delay the avocados from turning brown.\n" +
            "Add the chopped onion, cilantro, black pepper, and chiles. Chili peppers vary individually in their hotness. So, start with a half of one chili pepper and add to the guacamole to your desired degree of hotness.\n" +
            "Remember that much of this is done to taste because of the variability in the fresh ingredients. Start with this recipe and adjust to your taste.\n" +
            "Chilling tomatoes hurts their flavor, so if you want to add chopped tomato to your guacamole, add it just before serving.\n" +
            "4 Serve: Serve immediately, or if making a few hours ahead, place plastic wrap on the surface of the guacamole and press down to cover it and to prevent air reaching it. (The oxygen in the air causes oxidation which will turn the guacamole brown.) Refrigerate until ready to serve.");
    perfectGuacamole.setIngredients(ingredientesGuacamole);
    perfectGuacamole.setNotes(notes);
    perfectGuacamole.setServings(4);

    categoryRepository.save(newCategory);
    recipeRepository.save(perfectGuacamole);

Сущность рецепта:

@Entity
public class Recipe {

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

private String description;
private Integer prepTime;
private Integer cookTime;
private Integer servings;
private String source;
private String url;

@Lob
private String directions;

@Lob
private Byte[] image;

@Enumerated(value = EnumType.STRING)
private Difficulty difficulty;

@OneToOne(cascade = CascadeType.ALL)
private Notes notes;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "recipe")
private Set<Ingredient> ingredients;


@ManyToMany
@JoinTable(name = "recipe_category",
        joinColumns = @JoinColumn(name = "recipe_id"),
        inverseJoinColumns = @JoinColumn(name = "category_id")
)
private Set<Category> categories = new HashSet<>();


public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public Integer getPrepTime() {
    return prepTime;
}

public void setPrepTime(Integer prepTime) {
    this.prepTime = prepTime;
}

public Integer getCookTime() {
    return cookTime;
}

public void setCookTime(Integer cookTime) {
    this.cookTime = cookTime;
}

public Integer getServings() {
    return servings;
}

public void setServings(Integer servings) {
    this.servings = servings;
}

public String getSource() {
    return source;
}

public void setSource(String source) {
    this.source = source;
}

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}

public String getDirections() {
    return directions;
}

public void setDirections(String directions) {
    this.directions = directions;
}

public Byte[] getImage() {
    return image;
}

public void setImage(Byte[] image) {
    this.image = image;
}

public Difficulty getDifficulty() {
    return difficulty;
}

public void setDifficulty(Difficulty difficulty) {
    this.difficulty = difficulty;
}

public Notes getNotes() {
    return notes;
}

public void setNotes(Notes notes) {
    this.notes = notes;
}

public Set<Ingredient> getIngredients() {
    return ingredients;
}

public void setIngredients(Set<Ingredient> ingredients) {
    this.ingredients = ingredients;
}


public Set<Category> getCategories() {
    return categories;
}

public void setCategories(Set<Category> categories) {
    this.categories = categories;
}

}

Категория Entity:

@Entity
public class Category {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;


@ManyToMany(mappedBy = "categories")
private Set<Recipe> recipes = new HashSet<>();

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}


public Set<Recipe> getRecipes() {
    return recipes;
}

public void setRecipes(Set<Recipe> recipes) {
    this.recipes = recipes;
}
}

Наблюдение: я уже знаю, что для работы я должен использовать аннотацию Cascate, дело в том, что она ровная, она не работает.

Я уже пробовал использовать Fetch.eager на всех сторонах отношений, и это тоже не работает, и даже установите для свойства spring.jpa.open-in-view значение false.

Может быть, мне стоит реализовать настраиваемый репозиторий слой с Entity Manager внутри него, чтобы обрабатывать его "вручную". Но я не знаю, как мне поступить.

Надеюсь, вы, ребята, сможете найти решение. Заранее спасибо.

РЕДАКТИРОВАТЬ: Отдельная сущность - Категория.

1 Ответ

0 голосов
/ 08 мая 2020

Не могли бы вы добавить каскадный атрибут к аннотации @ManyToMany в модели рецепта и повторить попытку? Код будет выглядеть так:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "recipe_category",
        joinColumns = @JoinColumn(name = "recipe_id"),
        inverseJoinColumns = @JoinColumn(name = "category_id")
)
private Set<Category> categories = new HashSet<>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...