I have a legacy db where I want to join an entity using a non-primary composite key.
The table definitions:
create table product
(
id bigint not null
primary key,
accounting_area_id varchar(255) not null,
domain_object_id varchar(255) not null,
tenant_id varchar(255) not null,
display_name varchar(255) not null,
kind varchar(255) not null,
constraint product_un
unique (tenant_id, accounting_area_id, domain_object_id),
foreign key (kind, tenant_id) references kind (domain_object_id, tenant_id)
);
create table kind
(
id bigint not null
primary key,
domain_object_id varchar(255) not null,
tenant_id varchar(255) not null,
display_name varchar(255) not null,
constraint kind_un
unique (tenant_id, domain_object_id)
);
As you can see Product
references Kind
by foreign key (kind, tenant_id) references kind (domain_object_id, tenant_id)
.
The entity definitions (some details ommited for brevity):
@Entity
@Table(name = "product")
public class ProductEntity {
@Id
@GeneratedValue
private long id;
@NaturalId
@Embedded
@AttributeOverrides({@AttributeOverride(name = "domain_object_id", column = @Column(name = "domain_object_id")),
@AttributeOverride(name = "accounting_area_id",
column = @Column(name = "accounting_area_id")),
@AttributeOverride(name = "tenant_id", column = @Column(name = "tenant_id"))
})
private AccountingAreaEntityDomainObjectTuple domainObjectTuple;
@Column(name = "display_name")
private String displayName;
@ManyToOne
@JoinColumns(value = {
@JoinColumn(name = "wine_kind", referencedColumnName = "domain_object_id", insertable = false, updatable = false),
@JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id", insertable = false, updatable = false)
}, foreignKey = @ForeignKey(name = "product_kind_tenant_id_fkey"))
private KindEntity kind;
}
@Entity
@Table(name = "kind")
public class KindEntity {
@Id
@GeneratedValue
private long id;
@NaturalId
@Embedded
@AttributeOverrides({ @AttributeOverride (name = "domain_object_id", column = @Column (name = "domain_object_id")),
@AttributeOverride(name = "tenant_id", column = @Column(name = "tenant_id"))
})
private TenantEntityDomainObjectTuple domainObjectTuple;
@Column(name = "display_name", nullable = false)
private String displayName;
}
@Embeddable
@MappedSuperclass
public class TenantEntityDomainObjectTuple
{
@Column(name = "domain_object_id", nullable = false)
private String domainObjectId;
@Column (name = "tenant_id", nullable = false)
private String tenantId;
}
@Embeddable
public class AccountingAreaEntityDomainObjectTuple extends TenantEntityDomainObjectTuple
{
@Column (name = "accounting_area_id", nullable = false)
private String accountingAreaId;
}
However, this throws the following exception:
org.hibernate.AnnotationException: referencedColumnNames(domain_object_id, tenant_id) of ProductEntity.kind referencing KindEntity not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:333)
...
Is it even possible to join an entity using a non-primary composite key?
CodePudding user response:
It's possible through hbm.xml, but the annotation model does not support this yet. You can track https://hibernate.atlassian.net/browse/HHH-15355 which is about adding support for this to the annotation model.