簡體   English   中英

“分離的實體傳遞給持久化”當我嘗試持久化具有多對多關系的實體時

[英]“detached entity passed to persist” When i try to persist an Entity with ManyToMany relationship

我知道有很多類似的問題,但是我沒有遇到一個可以解決我的問題的問題,而且我已經嘗試了所有可能的方法-我閱讀了。

所以問題基本上是我無法在我的代碼中持久化一個實體“Recipe”的實例,它與我的h2數據庫中的另一個“Category”有ManyToMany關系,而之前沒有在代碼流中持久化類別實例。

這個“配方”實體已經在其聲明中包含許多其他實體(Notes - OneToOne,成分 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
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。

也許我應該實現一個自定義存儲庫層,里面有一個實體管理器來“手動”處理它。 但我不知道我應該如何進行。

我希望你們能找到解決辦法。 提前致謝。

編輯:分離的實體是類別。

您能否將級聯屬性添加到配方 model 中的@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<>();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM