Mein Ziel ist es, eine Rezeptureinheit zu speichern, die mehrere Zutaten enthalten kann, wobei mehrere Zutaten in verschiedenen Rezepten verwendet werden können. (Schritt 2: Zutaten sollten nicht zweimal gespeichert werden.) Aber Hibernate kann nicht einmal das Rezept mit Zutaten speichern. Es führt immer zu einer Ausnahme basierend auf falschen Typen und so weiter. Hier ist die Abbildung und die Beispiele:Hibernate @ManyToMany aufgrund ungültiger Typen nicht möglich
Datenbank:
Table "public.ingredient_recipe_rel"
Column | Type | Modifiers
------------------------+-----------------------+-----------
irr_rcp_id | bigint | not null
irr_ing_ingredient | character varying(40) | not null
irr_ing_acc_identifier | bigint | not null
Indexes:
"ingredient_recipe_rel_pkey" PRIMARY KEY, btree (irr_ing_ingredient, irr_ing_acc_identifier, irr_rcp_id)
"fk_irr_ing_ingredient_idx" btree (irr_ing_ingredient)
"fk_irr_rcp_id_idx" btree (irr_rcp_id)
Foreign-key constraints:
"fk_irr_ing_ingredient" FOREIGN KEY (irr_ing_ingredient, irr_ing_acc_identifier) REFERENCES ingredient(ing_ingredient, ing_acc_identifier)
"fk_irr_rcp_id" FOREIGN KEY (irr_rcp_id) REFERENCES recipe(rcp_id)
Table "public.recipe"
Column | Type | Modifiers
--------------------+-----------------------------+---------------------------------------------------------
rcp_id | bigint | not null default nextval('recipe_rcp_id_seq'::regclass)
rcp_title | character varying(100) | not null
rcp_description | text | not null
rcp_acc_identifier | bigint | not null
rcp_defaultpersons | integer | not null
rcp_difficulty | integer |
rcp_rating | integer |
rcp_idletime | integer |
rcp_cooktime | integer |
rcp_calories | character varying(20) |
rcp_source | character varying(500) |
rcp_photourl | character varying(512) |
rcp_updatetime | timestamp without time zone | not null
rcp_cookcounter | integer | not null
Indexes:
"recipe_pkey" PRIMARY KEY, btree (rcp_id)
"fk_rcp_acc_identifier_idx" btree (rcp_acc_identifier)
Foreign-key constraints:
"fk_rcp_acc_identifier" FOREIGN KEY (rcp_acc_identifier) REFERENCES accesskey(acc_identifier)
Referenced by:
TABLE "ingredient_recipe_rel" CONSTRAINT "fk_irr_rcp_id" FOREIGN KEY (irr_rcp_id) REFERENCES recipe(rcp_id)
TABLE "recipe_basiccategory_rel" CONSTRAINT "fk_rbc_rcp_id" FOREIGN KEY (rbc_rcp_id) REFERENCES recipe(rcp_id)
Table "public.ingredient"
Column | Type | Modifiers
--------------------+------------------------+-----------------------------------------------------------------
ing_ingredient | character varying(40) | not null
ing_acc_identifier | bigint | not null
ing_amount | real |
ing_unit | character varying(20) |
ing_rcp_id | bigint | not null default nextval('ingredient_ing_rcp_id_seq'::regclass)
ing_group | character varying(100) |
Indexes:
"ingredient_pkey" PRIMARY KEY, btree (ing_ingredient, ing_acc_identifier)
"fk_ing_identifier_idx" btree (ing_acc_identifier)
Foreign-key constraints:
"fk_ing_acc_identifier" FOREIGN KEY (ing_acc_identifier) REFERENCES accesskey(acc_identifier)
Referenced by:
TABLE "ingredient_recipe_rel" CONSTRAINT "fk_irr_ing_ingredient" FOREIGN KEY (irr_ing_ingredient, irr_ing_acc_identifier) REFERENCES ingredient(ing_ingredient, ing_acc_identifier)
RECI PE
@Entity
@Table(name = "RECIPE")
public class Recipe implements Serializable
{
private static final long serialVersionUID = 1L;
@SequenceGenerator(allocationSize=1, initialValue=1, sequenceName="recipe_rcp_id_seq", name="recipe_rcp_id_seq")
@GeneratedValue(generator="recipe_rcp_id_seq", strategy=GenerationType.SEQUENCE)
@Id
@Column(name = "rcp_id")
private Long rcpId;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "INGREDIENT_RECIPE_REL",
joinColumns = {
@JoinColumn(name = "irr_rcp_id", nullable = false, updatable = false)
},
inverseJoinColumns = {
@JoinColumn(name = "irr_ing_ingredient", nullable = false, updatable = false)
@JoinColumn(name = "irr_ing_acc_identifier", nullable = false, updatable = false)
})
private List<Ingredient> ingredients = new ArrayList<>();
//More code, getters, setters
}
ZUTAT
@Entity
@IdClass(IngredientPk.class)
@Table(name = "INGREDIENT")
public class Ingredient implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ing_ingredient")
private String ingredient;
@Id
@Column(name = "ing_acc_identifier")
private Long identifier;
@ManyToMany(mappedBy = "ingredients")
private List<Recipe> recipes;
//More code, getters, setters
}
Dieser Code ist nicht einmal einsetzbar in Wildfly. Ich erhalte die folgenden Ausnahmen, aber ich verstehe nicht, warum, weil es die Aufgabe von Hibernate ist die richtigen Typen anwenden:
Caused by: org.hibernate.HibernateException: Wrong column type in public.ingredient_recipe_rel for column irr_ing_ingredient. Found: varchar, expected: int8
Trotzdem habe ich versucht, mein Rezept Einheit zu ändern (obwohl ich nicht nötig hatte, diese zu verwenden versuchen sie vorher):
@Entity
@Table(name = "RECIPE")
public class Recipe implements Serializable
{
private static final long serialVersionUID = 1L;
@SequenceGenerator(allocationSize=1, initialValue=1, sequenceName="recipe_rcp_id_seq", name="recipe_rcp_id_seq")
@GeneratedValue(generator="recipe_rcp_id_seq", strategy=GenerationType.SEQUENCE)
@Id
@Column(name = "rcp_id")
private Long rcpId;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "INGREDIENT_RECIPE_REL",
joinColumns = {
@JoinColumn(name = "irr_rcp_id", columnDefinition = "INT8 NOT NULL")
},
inverseJoinColumns = {
@JoinColumn(name = "irr_ing_ingredient", columnDefinition = "VARCHAR(40) NOT NULL"),
@JoinColumn(name = "irr_ing_acc_identifier", columnDefinition = "INT8 NOT NULL")
})
private List<Ingredient> ingredients = new ArrayList<>();
//More code, getters, setters
}
Dieser Code einsetzbarer in Wildfly ist, aber es sieht so aus, dass dieser Code noch nicht stimmt. Wenn ich versuche, ein Rezept zu speichern, die zwei Zutaten, ich die folgende Ausnahme erhalten, wenn ich versuche, den folgenden Test auszuführen:
@Test
public void persistenceOfRecipeWithIngredientSuccessful()
{
//given
createUser(USER_ID1);
long recipeIdentifier = 1;
long ingredient1Identifier = 2;
long ingredient2Identifier = 3;
//create identifiers to fulfill FK constraint
createAccessKey(recipeIdentifier);
createAccessKey(ingredient1Identifier);
createAccessKey(ingredient2Identifier);
//setting of mandatory fields are omitted to shorten code
Recipe recipe = new Recipe();
recipe.setIdentifier(recipeIdentifier);
List<Recipe> recipes = new ArrayList<>();
recipes.add(recipe);
List<Ingredient> ingredients = new ArrayList<>();
Ingredient ingredient1 = new Ingredient();
ingredient1.setIngredient("Flour");
ingredient1.setIdentifier(ingredient1Identifier);
ingredient1.setRecipes(recipes);
ingredients.add(ingredient1);
Ingredient ingredient2 = new Ingredient();
ingredient2.setIngredient("Sugar");
ingredient2.setIdentifier(ingredient2Identifier);
ingredient2.setRecipes(recipes);
ingredients.add(ingredient2);
recipe.setIngredients(ingredients);
//when
RecipeService recipeService = new RecipeService();
recipeService.setEntityManager(getEntityManager());
getEntityManager().getTransaction().begin();
//PERSIST CRASHES.....
recipeService.getEntityManager().persist(recipe);
getEntityManager().getTransaction().commit();
//then
//doing asserts...
}
Caused by: org.postgresql.util.PSQLException: ERROR: column "irr_ing_acc_identifier" is of type bigint but expression is of type character varying Hint: You will need to rewrite or cast the expression.
Irgendwelche Ideen über das, was hier vor sich geht?
Sie generieren Entitäten durch Eclipse? –
@ HassamAbdelillah Die ersten, aber seitdem habe ich einige manuell hinzugefügt. Diese Zuordnungen werden jedoch nicht generiert. – Bevor
Ich habe einige Probleme mit der Erstellung von Eclipse-Entitäten, wenn Composite-Schlüssel einmal vorhanden sind. Die Klasse @IdClass IngredientPK hat entweder die richtigen Typen? –