0

ManyToMany: Recipes <--> Ingredients But with extra fields.

@Entity
@Getter
@Setter
@RequiredArgsConstructor
public class Recipe {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private boolean vegetarian;
    private String description;

    @OneToMany(
            mappedBy = "recipe",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<RecipesHasIngredients> ingredients = new ArrayList<>();
}
@Entity
@Getter
@Setter
@NaturalIdCache
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@RequiredArgsConstructor
public class Ingredient {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NaturalId
    private String name;

    private Boolean isVegetarian;
}
@Entity
@Getter
@Setter
@RequiredArgsConstructor
public class RecipesHasIngredients {
    @EmbeddedId
    private RecipesHasIngredientsId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("recipeId")
    private Recipe recipe;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("ingredientId")
    private Ingredient ingredient;

    private String amount;
}
@Embeddable
@Getter
@Setter
@EqualsAndHashCode(of = {"recipeId", "ingredientId"})
@RequiredArgsConstructor
public class RecipesHasIngredientsId implements Serializable {
    private Long recipeId;

    private Long ingredientId;
}
@RepositoryRestResource(collectionResourceRel = "recipes", path = "recipes")
interface RecipesRepository extends JpaRepository<Recipe, Long>, RecipesRepositoryCustom {
}

The DB is created fine, and the app loads properly. However, the moment I try to POST new Recipe with associated to a new Ingredient there is an error in the mapping layer that I can't seem to locate.

For reference, this is the json I POST to /recipes:

{
  "vegetarian": true,
  "description": "something",
  "owner": "http://localhost:8080/users/1",
  "ingredients": [
    {
      "amount": "2.5kg",
      "name": "carrot",
      "isVegetarian": true
    }
  ]
}

Running:

curl http://localhost:8080/recipes/ -X POST -d '{"vegetarian": true, "description": "something", "ingredients":[{"amount": "2.5kg", "name": "carrot", "isVegetarian": true}]}' -H "Content-Type: application/json"

Triggers error

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: attempted to assign id from null one-to-one property [+++.recipesapp.ingredients.RecipesHasIngredients.ingredient]; nested exception is org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [+++.recipesapp.ingredients.RecipesHasIngredients.ingredient]] with root cause

So: attempted to assign id from null one-to-one property

Does anybody know what am I doing wrong?

José Cabo
  • 6,149
  • 3
  • 28
  • 39
  • What does the object built from that JSON look like? The error itself is because the 'recipe' and 'ingredient' references are null - the JSON only has a name, amount and isVegetarian so isn't likely building you what you think it is. The issue might be that you've setup your JPA mappings fine, but neglected the JSON mappings to manage how you will build these entities from this JSON and need to fix it up before giving it to JPA. Try reading data from the database and seeing the JSON output it gives you on the fetch (you might get a stack overflow on the circular/bidirectional relationship). – Chris Nov 29 '22 at 16:00

0 Answers0