How to have the same column as part of composite id and many to one relationship?

We have a legacy code base and can’t move to annotations. Please suggest a hbm xml mapping based solution.

Example:
We have 3 entities: Manager, Employee, and Company
Manager and Employee has a one-to-many relationship. And both of these entities have a composite id with SEQ and COMPANY_FK. **Now the problem arises in case of Employee entity, where COMPANY_FK is part of the composite id and many-to-one relationship as well.
**

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity:
Employee column: COMPANY_FK
(should be mapped with insert="false" update="false")

But if I map it as insert=false and update=false, then the MANGER_FK column won’t be populated.

Entity: MANAGER
Columns:
MANAGER_SEQ
COMPANY_FK

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="domain" default-cascade="merge" auto-import="false">
	<class name="Manager" entity-name="MANAGER" table="MANAGER">
		<composite-id>
			<key-property name="Id" column="MANAGER_SEQ" type="Integer" access="property"/>
			<key-many-to-one name="Company" column="COMPANY_FK" class="Company" access="property" lazy="false"/>
		</composite-id>

		<set name="EmployeeSet" inverse="true" access="property" batch-size="100">
			<key>
				<column name="MANAGER_FK"/>
				<column name="COMPANY_FK"/>
			</key>
			<one-to-many class="Employee" />
		</set>
	</class>
</hibernate-mapping>

Entity: Employee
Columns:
EMPLOYEE_SEQ
COMPANY_FK
MANAGER_FK

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="domain" default-cascade="merge" auto-import="false">
	<class name="Employee" entity-name="EMPLOYEE" table="EMPLOYEE">
		<composite-id>
			<key-property name="Id" column="EMPLOYEE_SEQ" type="Integer" access="property"/>
			<key-many-to-one name="Company" column="COMPANY_FK" class="Company" access="property" lazy="false"/>
		</composite-id>

		<many-to-one name="Manager" class="Manager" unique="true">
			<column name="MANAGER_FK"/>
			<column name="COMPANY_FK"/>
		</many-to-one>

	</class>
</hibernate-mapping>

Why do you need the primary key of the EMPLOYEE table to be a composite? From the naming, it seems that you are using a sequence anyway, so what’s the point?

If you want to be able to map this kind of model, you have to introduce an additional property managerFk and make the Manager many-to-one insert="false" update="false"

@beikov All our problems are arising as part of Postgres Migration. Since our table size is huge we need to partition the table, and Postgres does not support Global Indexes, so now all our queries require the Partition Key that is COMPANY_FK in our case, to have partition pruning.

This is the reason we are moving to a composite id, it will solve 2 problems:

  1. Joins will be on 2 columns now, sequence and COMPANY_FK
  2. Inserts and Deletes will also have COMPANY_FK in where clause.

We want the many-to-one relationship to be on 2 columns, sequence and COMPANY_FK.
Also since we have a legacy application we can’t move to Annotations. So we need to model this in HBM XML mapping files.

A join-formula would suffice also I believe.

		<set name="EmployeeSet" inverse="true" access="property" batch-size="100">
			<key>
				<column name="MANAGER_FK"/>
				<formula>COMPANY_FK</formula>
			</key>
			<one-to-many class="Employee" />
		</set>