简体   繁体   English

Spring Boot - 外键 PostgreSQL 数据库中的空值

[英]Spring Boot - null value in foreign key PostgreSQL database

I have Recipe class:我有Recipe课:

@Entity
@Table(name="recipestest")
public class Recipe {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String title;

    private String description;

    @OneToMany(mappedBy="recipe")
    private List<Ingredient> ingredients;

    public Recipe(String title, String description, List<Ingredient> ingredients) {
        this.title = title;
        this.description = description;
        this.ingredients = ingredients;
    }

    public Recipe() { }

    /* getters and setters */
}

And Ingredient class:Ingredient类:

@Entity
@Table(name="ingredients")
public class Ingredient {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;

    private int quantity;

    private String unit;

    @ManyToOne
    @JoinColumn(name="recipe_id", nullable=false)
    private Recipe recipe;

    public Ingredient(String name, int quantity, String unit) {
        this.name = name;
        this.quantity = quantity;
        this.unit = unit;
    }

    public Ingredient() { }

    /* all getters and setters */
}

I've created two tables recipestest and ingredients (especially) in PostgreSQL:我在 PostgreSQL 中创建了两个表recipestestingredients (尤其是):

CREATE TABLE ingredients (
    id bigserial NOT NULL PRIMARY KEY,
    name text NOT NULL,
    quantity integer NOT NULL,
    unit text NOT NULL,
    recipe_id integer NOT NULL REFERENCES recipestest(id)
)

Both Recipe and Ingredient have repositories: RecipeIngredient都有存储库:

public interface RecipeRepository extends JpaRepository<Recipe, Long> {
}

public interface IngredientRepository extends JpaRepository<Ingredient, Long> {
}

There is this createRecipe - method which stores an objects in the database:有这个createRecipe - 在数据库中存储对象的方法:

@PostMapping(path = "")
public Recipe createRecipe(@RequestBody Recipe recipe) {
    ingredientRepository.saveAll(recipe.getIngredients());
    return recipeRepository.save(recipe);
}

I transmit this JSON via POST in Postman:我通过 Postman 中的 POST 传输此 JSON:

{
    "title": "cake1",
    "description": "description1",
    "ingredients": [
        {
            "name": "ingredient1",
            "quantity": 8,
            "unit": "g"
        },
        {
            "name": "ingredient2",
            "quantity": 8,
            "unit": "ml"
        }
    ]
}

I want to recipe_id in ingredients table be a id of respective recipetest entities, but I've got such an error:我想recipe_idingredients表是一个id对应的recipetest实体,但我有这样的错误:

{
    "timestamp": "2019-12-29T18:06:07.979+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
}

And error in IntelliJ IDEA's terminal: IntelliJ IDEA 终端中的错误:

org.postgresql.util.PSQLException: ERROR: null value in column "recipe_id" violates not-null constraint
Detail: Failing row contains (47, ingredient1, 8, g, null)

My application.properties and pom.xml我的application.propertiespom.xml

You are using :您正在使用 :

@JoinColumn(name = "recipe_id", nullable = false)
private Recipe recipe;

Which mean that Recipe should not be null, but as we see in your JSon file, there are only the list of Ingredients without Recipes , which cause this problem.这意味着 Recipe 不应为空,但正如我们在您的 JSon 文件中看到的,只有没有RecipesIngredients列表,这会导致此问题。


There are many ways, one of them is by using CascadeType.PERSIST , or CascadeType.ALL based on what you want to do :有很多方法,其中之一是根据您要执行的操作使用CascadeType.PERSISTCascadeType.ALL

@OneToMany(mappedBy="recipe", cascade = CascadeType.PERSIST)
private List<Ingredient> ingredients;

Then in your service you can only save the recipe :然后在您的服务中,您只能保存配方:

@PostMapping(path = "")
public Recipe createRecipe(@RequestBody Recipe recipe) {
    //ingredientRepository.saveAll(recipe.getIngredients());
    return recipeRepository.save(recipe);
}

Advice建议

for the id you have to use Long which accept null, not a primitive type :对于 id,您必须使用 Long 接受 null,而不是原始类型:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM