Jan Krupiński
Jan Krupiński

Reputation: 405

Spring Boot - null value in foreign key PostgreSQL database

I have Recipe class:

@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:

@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:

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:

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:

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

I transmit this JSON via POST in Postman:

{
    "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:

{
    "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:

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

Upvotes: 1

Views: 1946

Answers (1)

Youcef LAIDANI
Youcef LAIDANI

Reputation: 59970

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.


There are many ways, one of them is by using CascadeType.PERSIST, or CascadeType.ALL based on what you want to do :

@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 :

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

Upvotes: 2

Related Questions