Both key column and map-key are PK

How do I create a map property that has both key column and a map key as parts of PK of the detail class?

Like this:

<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>

I need to avoid creating a surrogate key in PersonName class that would require a special handling. Json shown below should be automatically persisted in the DB, inserting and updating detail record when necessary, based on PersonId-code key.

It’s natural that “code” property identifies the row together with the person Id.

I tried different combinations of “inverse”, “not-null” etc. I admit that I don’t fully get how it works. I get different error messages, like:

ERROR: null value in “person” column violates NOT NULL constraint
Details: Erroreous row contains (null, null, lastname, ffffirst, null, null).

or:

org.hibernate.MappingException: Repeated column in mapping for entity: PersonName column: person (should be mapped with insert=”false” update=”false”)

It should look like this, if represented as json:

{
    "birthDate": "33-44-55",
    "names": {
        "mainName": {
            "lastName": "lastname",
            "firstName": "ffffirst"
        },
        "maidenName": {
            "lastName": "lastname1",
            "firstName": "ffffirst2"
        },
        "old": {
            "lastName": "lastname3",
            "firstName": "ffffirst4"
        }

    }
}

UPD (clarification of question) Actually this is a main goal – the system should create master and all details when posted with this json. This json is converted into the mapped classes. If master has an “id” populated, the system should update both master and details, adding new entries when needed. Details (“names” map entries) should not have any surrogate “id” specified. They are identified by master’s “personId” field and “code” field.

** clarification 2 ** As shown in the example json, the map key is a string, not a composite key. As seen in mapping xml, this is all dynamic mapping. No additional class, that couldn’t be instantiated automatically from the json, should be written.

Hope it’s possible!

To get the whole picture, the table is generated OK, I like it:

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
)

Answer

It’s impossible. Use mongodb or write your own ORM.

Leave a Reply

Your email address will not be published. Required fields are marked *