Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate以列或类名作为键映射_Java_Hibernate_Postgresql_One To Many - Fatal编程技术网

Java Hibernate以列或类名作为键映射

Java Hibernate以列或类名作为键映射,java,hibernate,postgresql,one-to-many,Java,Hibernate,Postgresql,One To Many,我一天中大部分时间都在为这个问题发愁,根本找不到这个问题的答案 我有一个PostgreSQL方案,如下所示: +---------+ 1-n +-------------+ 1-1 +------+ | Product |-------->| ProductSpec |-------->| Spec | +---------+ +-------------+ +------+ CREATE TABLE sellable.sellables (

我一天中大部分时间都在为这个问题发愁,根本找不到这个问题的答案

我有一个PostgreSQL方案,如下所示:

+---------+ 1-n +-------------+ 1-1 +------+ | Product |-------->| ProductSpec |-------->| Spec | +---------+ +-------------+ +------+
CREATE TABLE sellable.sellables
(
  sll_id serial NOT NULL, -- Sellable ID
  sll_date_created timestamp with time zone NOT NULL DEFAULT now(), -- Date the item was created
  sll_date_updated timestamp with time zone NOT NULL DEFAULT now(), -- Date the item was last updated
  sll_title character varying(255) NOT NULL, -- Title of the item
  sll_desc text NOT NULL, -- Textual description of the item
  CONSTRAINT sellables_pkey PRIMARY KEY (sll_id)
)

CREATE TABLE sellable.products
(
  sll_id integer NOT NULL, -- Sellable ID
  mfr_id integer NOT NULL, -- ID of the product manufacturer
  CONSTRAINT products_pkey PRIMARY KEY (sll_id),
  CONSTRAINT products_mfr_id_fkey FOREIGN KEY (mfr_id)
      REFERENCES sellable.manufacturers (mfr_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT products_sll_id_fkey FOREIGN KEY (sll_id)
      REFERENCES sellable.sellables (sll_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE TABLE sellable.specifications
(
  spc_id serial NOT NULL, -- Specification ID
  spc_classname character varying(127) NOT NULL, -- Specification subclass
  CONSTRAINT specifications_pkey PRIMARY KEY (spc_id)
)

CREATE TABLE sellable.productspecifications
(
  ps_id serial NOT NULL, -- Primary key
  sll_id integer NOT NULL, -- Product the specification is linked to
  spc_id integer NOT NULL, -- Specification the product is associated with
  CONSTRAINT productspecifications_pkey PRIMARY KEY (ps_id),
  CONSTRAINT productspecifications_sll_id_fkey FOREIGN KEY (sll_id)
      REFERENCES sellable.products (sll_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT productspecifications_spc_id_fkey FOREIGN KEY (spc_id)
      REFERENCES sellable.specifications (spc_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT productspecifications_spc_id_key UNIQUE (spc_id)
)
DB模式如下所示:

+---------+ 1-n +-------------+ 1-1 +------+ | Product |-------->| ProductSpec |-------->| Spec | +---------+ +-------------+ +------+
CREATE TABLE sellable.sellables
(
  sll_id serial NOT NULL, -- Sellable ID
  sll_date_created timestamp with time zone NOT NULL DEFAULT now(), -- Date the item was created
  sll_date_updated timestamp with time zone NOT NULL DEFAULT now(), -- Date the item was last updated
  sll_title character varying(255) NOT NULL, -- Title of the item
  sll_desc text NOT NULL, -- Textual description of the item
  CONSTRAINT sellables_pkey PRIMARY KEY (sll_id)
)

CREATE TABLE sellable.products
(
  sll_id integer NOT NULL, -- Sellable ID
  mfr_id integer NOT NULL, -- ID of the product manufacturer
  CONSTRAINT products_pkey PRIMARY KEY (sll_id),
  CONSTRAINT products_mfr_id_fkey FOREIGN KEY (mfr_id)
      REFERENCES sellable.manufacturers (mfr_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT products_sll_id_fkey FOREIGN KEY (sll_id)
      REFERENCES sellable.sellables (sll_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE TABLE sellable.specifications
(
  spc_id serial NOT NULL, -- Specification ID
  spc_classname character varying(127) NOT NULL, -- Specification subclass
  CONSTRAINT specifications_pkey PRIMARY KEY (spc_id)
)

CREATE TABLE sellable.productspecifications
(
  ps_id serial NOT NULL, -- Primary key
  sll_id integer NOT NULL, -- Product the specification is linked to
  spc_id integer NOT NULL, -- Specification the product is associated with
  CONSTRAINT productspecifications_pkey PRIMARY KEY (ps_id),
  CONSTRAINT productspecifications_sll_id_fkey FOREIGN KEY (sll_id)
      REFERENCES sellable.products (sll_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT productspecifications_spc_id_fkey FOREIGN KEY (spc_id)
      REFERENCES sellable.specifications (spc_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT productspecifications_spc_id_key UNIQUE (spc_id)
)
下面列出了Hibernate生成的查询(我没有按照类的方式进行修剪,以防在未桥接的查询中出现问题)。一个明显的问题是,它试图在不插入模式名称的情况下查询specifications表

select
    bicycle0_.sll_id as sll1_0_3_,
    bicycle0_2_.sll_date_created as sll2_0_3_,
    bicycle0_2_.sll_date_updated as sll3_0_3_,
    bicycle0_2_.sll_desc as sll4_0_3_,
    bicycle0_2_.sll_title as sll5_0_3_,
    bicycle0_1_.mfr_id as mfr2_1_3_,
    bicycle0_.btp_id as btp2_2_3_,
    manufactur1_.mfr_id as mfr1_4_0_,
    manufactur1_.mfr_name as mfr2_4_0_,
    specificat2_.sll_id as sll1_5_,
    specificat3_.spc_id as spc2_5_,
    (select
        a9.spc_classname 
    from
        specifications a9 
    where
        a9.spc_id=specificat2_.spc_id) as formula0_5_,
    specificat3_.spc_id as spc2_5_1_,
    specificat3_.spc_classname as spc1_5_1_,
    specificat3_1_.dec_value as dec1_6_1_,
    specificat3_2_.bol_value as bol1_7_1_,
    specificat3_3_.int_value as int1_8_1_,
    specificat3_4_.str_value as str1_9_1_,
    bicycletyp4_.btp_id as btp1_3_2_,
    bicycletyp4_.btp_name as btp2_3_2_ 
from
    sellable.bicycles bicycle0_ 
inner join
    sellable.products bicycle0_1_ 
        on bicycle0_.sll_id=bicycle0_1_.sll_id 
inner join
    sellable.sellables bicycle0_2_ 
        on bicycle0_.sll_id=bicycle0_2_.sll_id 
left outer join
    sellable.manufacturers manufactur1_ 
        on bicycle0_1_.mfr_id=manufactur1_.mfr_id 
left outer join
    sellable.productspecifications specificat2_ 
        on bicycle0_.sll_id=specificat2_.sll_id 
left outer join
    sellable.specifications specificat3_ 
        on specificat2_.spc_id=specificat3_.spc_id 
left outer join
    sellable.specdecimalvalues specificat3_1_ 
        on specificat3_.spc_id=specificat3_1_.spc_id 
left outer join
    sellable.specbooleanvalues specificat3_2_ 
        on specificat3_.spc_id=specificat3_2_.spc_id 
left outer join
    sellable.specintegervalues specificat3_3_ 
        on specificat3_.spc_id=specificat3_3_.spc_id 
left outer join
    sellable.specstringvalues specificat3_4_ 
        on specificat3_.spc_id=specificat3_4_.spc_id 
left outer join
    sellable.bicycletypes bicycletyp4_ 
        on bicycle0_.btp_id=bicycletyp4_.btp_id 
where
    bicycle0_.sll_id=?
问题出在子查询中,它没有在specifications表名前添加架构

如果有人知道如何使查询正确,或者知道如何将类名直接用作Java映射键,我将非常感激被告知

编辑:我想使用映射而不是集合的原因是我想直接寻址规范集合中的项目。如果我使用集合,Hibernate生成的查询可以工作,但是我没有一个索引来访问元素。Product对象的API隐藏了规范存储在集合中的事实,并为每个单独的规范提供了getter和setter

如果我将规范设置为一组,我必须实现如下getter和setter:

@Transient
public BigDecimal getActualWeight () {
    BigDecimal  found   = null;
    for (Specification spec : this.specifications) {
        if (spec instanceof ActualWeightSpec) {
            found   = ((ActualWeightSpec) spec).getValue ();
            break;
        }
    }
    return found;
}

public Product setActualWeight (Number value) {
    ActualWeightSpec newWeight  = new ActualWeightSpec ();
    newWeight.setValue (value);

    for (Specification spec : this.specifications) {
        if (spec instanceof ActualWeightSpec) {
            ((ActualWeightSpec) spec).setValue (value);
            return this;
        }
    }

    this.specifications.add (newWeight);
    return this;
}
必须遍历一个集合才能获得单独的规范记录,这似乎是直接访问这些记录的一种非常糟糕的方式

我确实试着在内部维护一个hashmap,让规范的getter和setter接受和返回集,并在getter和setter中进行转换。那样的话,我只需要对规范进行一次迭代

private Product setSpecifications (Set <Specification> specs) {
    HashMap <String, Specification> specsMap = new HashMap <> ();

    for (Specification spec : specs) {
        specsMap.put(spec.getClassName (), spec);
    }

    this.specifications = specsMap;
    return this;
}
专用产品设置规范(设置规范){
HashMap specsMap=newhashmap();
用于(规格:规格){
specsMap.put(spec.getClassName(),spec);
}
本规范=规范映射;
归还这个;
}
这也不起作用,导致Hibernate抛出异常

严重:非法访问加载集合


您可以使用规范的内部映射,而不必用映射来干扰数据库。不要在Hibernate使用的getter或setter中初始化映射,但如果瞬态映射已经初始化,请检入getter(例如
getActualWeight
)。如果没有,则迭代一次规范并构建映射。顺便说一句,如果没有太多的规格,每次迭代应该不会造成太大的伤害。

不确定这是否会对您有所帮助,您的设置非常复杂,我无法轻松复制您的系统

“如果我使用一个集合,但是如果我使用一个MapKey集合作为规范类名的map,我会得到一个例外。”
集合有什么特别之处,它可以工作,但不是“非唯一”MapKey
接下来,错误消息是什么?第424行是什么?我想它实际上是生成的SQL语句的第424行,您这样写道:“(我不只是在规格表中使用外键到产品表中的原因是,规格可能属于产品继承树中不存在的东西,这些链接由其他交集表表示)。”你在尝试规范化规格表,对吗?你能把规范分为产品树规范和树外规范吗?我想我能,但在Java方面我有两个基本相同的类,它们唯一的区别是一个属于一种对象类型,另一个属于不同类型。规范类是针对各种数据类型的子类,这一事实使事情进一步复杂化。那么错误消息“relation Not Existence”是什么意思呢?您试图加入sll_id和spc_id,但产品中没有spc_id,规范中也没有sll_id……我已经在这些方面实施了一种方法。它看起来不错,但感觉有点不雅。Hibernate应该能够做到这一点,而不必像那样胡闹!很高兴你找到了解决办法。不确定这种方法的不雅性:您使用的映射更多地是关于有效的数据访问,而不是“好”的关系数据结构所必需的。