键列和映射键都是PK

时间:2014-06-03 17:39:25

标签: java hibernate jpa orm hibernate-mapping

如何创建一个map属性,其中包含键列和map键作为详细信息类的PK的一部分?

像这样:

<class entity-name="Person"  >
    <id name="id"/>
    <property name="birthDate" type="date"/>
    <map name="names">
        <key column="personId"/>
        <map-key type="string" column="code"/>
        <one-to-many class="PersonName" />
    </map>
</class>


<class entity-name="PersonName">
    <composite-id>
        <key-many-to-one name="personId" class="Person"/>
        <key-property name="code" type="string" length="32"/>
    </composite-id>
    <property name="lastName" type="string" length="64" index="nameSearch"/>
    <property name="firstName" type="string" length="64" index="nameSearch"/>
    <property name="middleName" type="string" length="64" index="nameSearch"/>
    <property name="isActual" type="boolean"/>
</class>

我需要避免在PersonName类中创建需要特殊处理的代理键。下面显示的Json应该自动保存在数据库中,必要时根据PersonId代码键插入和更新详细记录。

很自然的#34;代码&#34; property将该行与人员ID一起标识。

我尝试了&#34;逆&#34;,&#34; not-null&#34;的不同组合。我承认我没有完全了解它是如何工作的。我收到不同的错误消息,例如:

  

错误:&#34; person&#34;中的空值列违反NOT NULL约束
  详细信息:错误的行包含(null,null,lastname,ffffirst,null,null)。

或:

  

org.hibernate.MappingException:实体映射中的重复列:   PersonName列:person(应使用insert =&#34映射; false&#34; update =&#34; false&#34;)

如果表示为json:

,它应该如下所示
{
    "birthDate": "33-44-55",
    "names": {
        "mainName": {
            "lastName": "lastname",
            "firstName": "ffffirst"
        },
        "maidenName": {
            "lastName": "lastname1",
            "firstName": "ffffirst2"
        },
        "old": {
            "lastName": "lastname3",
            "firstName": "ffffirst4"
        }

    }
}

UPD(问题澄清) 实际上这是一个主要目标 - 系统应该在使用此json发布时创建master和所有细节。这个json被转换为映射类。如果主人有一个&#34; id&#34;填充后,系统应更新主数据和详细信息,并在需要时添加新条目。细节(&#34;姓名&#34;地图条目)不应该有任何代理人#id; id&#34;指定。它们由主人&#34; personId&#34;字段和&#34;代码&#34;字段。

**澄清2 ** 如示例json所示,map键是一个字符串,而不是一个复合键。如映射xml所示,这是所有动态映射。不应该写出不能从json自动实例化的其他类。

希望有可能!

为了全面了解,表格生成好了,我喜欢它:

CREATE TABLE personname
(
  personid character varying(32) NOT NULL,
  code character varying(32) NOT NULL,
  lastname character varying(64),
  firstname character varying(64),
  middlename character varying(64),
  isactual boolean,
  CONSTRAINT personname_pkey PRIMARY KEY (personid, code),
  CONSTRAINT fk_1skg5frawyftx8co9uawhc3r8 FOREIGN KEY (personid)
      REFERENCES person (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

2 个答案:

答案 0 :(得分:2)

我认为您的映射应如下所示:

对于嵌入式复合id,您需要一个嵌套的Key类(例如Person $ Key,尽管它也可以是外部类):

public static class Key {
    private Long personId;
    private String code;

    public Key(Long personId, String code) {
        this.personId = personId;
        this.code = code;
    }

    public Long getPersonId() {
        return personId;
    }

    public String getCode() {
        return code;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Key)) {
            return false;
        }
        Key k = (Key)obj;
        return personId.equals(k.personId) && code.equals(k.code);
    }

    @Override
    public int hashCode() {
        return 37*personId.hashCode() + code.hashCode();
    }
}

然后你的地图就像:

private Map<Key,PersonName> names = new HashMap<Key,PersonName>();

Hibernate映射:

<class entity-name="Person"  >
     <id name="id" column="id">
        <generator class="native"/>
    </id>
    <property name="birthDate" type="date"/>
    <map name="names" inverse="true">
        <composite-map-key class="Person$Key">
            <key-property name="personId"/>
            <key-property name="code"/>
        </composite-map-key>
        <one-to-many class="PersonName" />
    </map>
</class>

<class entity-name="PersonName">
    <composite-id name="id" class="Person">
        <key-property name="personId"/>
        <key-property name="code"/>
    </composite-id>
    <many-to-one name="person" class="Person"
        insert="false" update="false">
        <column name="personId"/>
        <column name="code"/>
    </many-to-one>
    <property name="lastName" type="string" length="64" index="nameSearch"/>
    <property name="firstName" type="string" length="64" index="nameSearch"/>
    <property name="middleName" type="string" length="64" index="nameSearch"/>
    <property name="isActual" type="boolean"/>
</class>

答案 1 :(得分:1)

这是不可能的。使用mongodb或编写自己的ORM。