【问题标题】:Hibernate @ManyToMany not possible due to invalid types由于类型无效,无法休眠 @ManyToMany
【发布时间】: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


【解决方案1】:

好的,几个小时后我发现出了什么问题。显然我必须定义引用的列。现在的解决方案如下所示:

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "INGREDIENT_RECIPE_REL",
        joinColumns = {
            @JoinColumn(name = "irr_rcp_id", referencedColumnName = "rcp_id")
        },
        inverseJoinColumns = {
            @JoinColumn(name = "irr_ing_ingredient", referencedColumnName = "ing_ingredient"),
            @JoinColumn(name = "irr_ing_acc_identifier", referencedColumnName = "ing_acc_identifier")
        })

【讨论】:

    猜你喜欢
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2022-08-22
    • 2020-04-14
    • 2014-12-12
    相关资源
    最近更新 更多