【发布时间】:2016-08-08 15:42:38
【问题描述】:
我的目标是存储一个可以有多种成分的配方实体,从而可以在不同的配方中使用多种成分。 (第 2 步:配料不应保存两次。)但 Hibernate 甚至无法保存至少包含配料的配方。它总是导致基于错误类型的异常等等。这是映射和示例:
数据库:
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)
食谱
@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
}
成分
@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
}
此代码甚至无法在 Wildfly 中部署。我得到以下异常,但我不明白为什么,因为 Hibernate 的任务是应用正确的类型:
原因:org.hibernate.HibernateException:输入错误的列类型 public.ingredient_recipe_rel 列 irr_ing_ingredient。成立: varchar,预期:int8
尽管如此,我还是尝试更改我的食谱实体(尽管我之前没有必要使用此尝试):
@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
}
此代码可在 Wildfly 中部署,但看起来此代码仍然错误。当我尝试保存包含两种成分的配方时,尝试执行以下测试时出现以下异常:
@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...
}
原因:org.postgresql.util.PSQLException: ERROR: column "irr_ing_acc_identifier" 是 bigint 类型,但表达式是类型 字符变化提示:您将需要重写或强制转换 表达。
对这里发生的事情有任何想法吗?
【问题讨论】:
-
你通过 Eclipse 生成实体?
-
@HassamAbdelillah 最初的那些,但从那以后我手动添加了一些。但不会生成这些映射。
-
我在 Eclipse 实体生成过程中遇到了一些问题,当有一次复合键时。 @IdClass IngredientPK 类也有正确的类型?
-
@HassamAbdelillah 是的,他们有。 (Eclipse 不生成 IdClasses,它创建了@EmbeddedIds)
标签: java hibernate postgresql wildfly