Is it possible to have a "Shared Primary Key" One to one relationship in Jmix?

I have the following situation in my project:

image

The DocItem entity has a One to one composition for ActivityBooking but this scheme does not meet my needs since I not only need to get the activity booking related to a DocItem, but also I need to query the database for the DocItem that owns an specific ActivityBooking, which seems impossible since the foreign key lives in the DocItem table.

By reading https://www.baeldung.com/jpa-one-to-one, on item 4.1, there is the possibility of having a shared primary key, where the primary key of an ActivityBooking instance would be the same as the DocItem that owns it. That seems to solve my problem because in that way I could fetch a DocItem from its owned ActivityBooking.

My question is, does Jmix allow that strategy?

Another option would be to create a second One to one relationship, having ActivityBooking as the owner but that seems not to be the correct way to go.

Yes this is supported, but requires some manual coding. Below is an example.

Root entity:

@JmixEntity
@Table(name = "ALPHA")
@Entity
public class Alpha {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @Column(name = "VERSION", nullable = false)
    @Version
    private Integer version;

    @InstanceName
    @Column(name = "NAME")
    private String name;

    @OneToOne(mappedBy = "alpha", fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn
    @Composition
    private Beta beta;

Nested entity:

@JmixEntity
@Table(name = "BETA")
@Entity
public class Beta {
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @Column(name = "VERSION", nullable = false)
    @Version
    private Integer version;

    @InstanceName
    @Column(name = "NAME")
    private String name;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    @JoinColumn(name = "ID")
    @OnDeleteInverse(DeletePolicy.CASCADE)
    private Alpha alpha;

The root entity detail view uses the standard entity_openComposition action:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
      title="msg://alphaDetailView.title"
      focusComponent="form">
    <data>
        <instance id="alphaDc"
                  class="com.company.demo.entity.Alpha">
            <fetchPlan extends="_base">
                <property name="beta" fetchPlan="_base"/>
            </fetchPlan>
            <loader id="alphaDl"/>
            <instance id="betaDc" property="beta"/>
        </instance>
    </data>
    <facets>
        <dataLoadCoordinator auto="true"/>
    </facets>
    <actions>
        <action id="saveAction" type="detail_saveClose"/>
        <action id="closeAction" type="detail_close"/>
    </actions>
    <layout>
        <formLayout id="form" dataContainer="alphaDc">
            <responsiveSteps>
                <responsiveStep minWidth="0" columns="1"/>
                <responsiveStep minWidth="40em" columns="2"/>
            </responsiveSteps>
            <textField id="nameField" property="name"/>
            <entityPicker id="betaField" property="beta">
                <actions>
                    <action id="entityOpenCompositionAction" type="entity_openComposition"/>
                    <action id="entityClearAction" type="entity_clear"/>
                </actions>
            </entityPicker>
        </formLayout>
        <hbox id="detailActions">
            <button id="saveAndCloseButton" action="saveAction"/>
            <button id="closeButton" action="closeAction"/>
        </hbox>
    </layout>
</view>

The action is configured in the view controller to set the ID of nested entity:

@Route(value = "alphas/:id", layout = MainView.class)
@ViewController(id = "Alpha.detail")
@ViewDescriptor(path = "alpha-detail-view.xml")
@EditedEntityContainer("alphaDc")
public class AlphaDetailView extends StandardDetailView<Alpha> {

    @Install(to = "betaField.entityOpenCompositionAction", subject = "transformation")
    private Object betaFieldEntityOpenCompositionActionTransformation(final Beta beta) {
        beta.setId(getEditedEntity().getId());
        return beta;
    }
}

That’s basically it, the one-to-one composition will work as usual (see e.g. Data Modeling: Composition :: Jmix Documentation), but the root and nested entities will have the same ID.

Attached the test project:
demo.zip (92.1 KB)