Home > OS >  Query for Foreign Key string ID without fetching the actual entity
Query for Foreign Key string ID without fetching the actual entity

Time:11-09

Given the model below, when fetching an entity from the myentity table with JPA, is there a way to prevent the secondary fetch that would get the entity from the anotherentity table, but would provide us with the externalPk String value (which is used as a Foreign Key) itself?

As much as I understand that due to the declared types in Java it wouldn't specifically be possible, I do wonder if there's way to access that information without the extra fetch considering it is indeed right there in that myentity table as an actual varchar column.

If it can help, we use EclipseLink as our JPA provider.

Current model

@Entity
@Table(name = "myentity")
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@IdClass(MyIdClass.class)
public class MyEntity {

    @Id
    @Column(updatable = false)
    private String foo;

    @Id
    @Column(updatable = false)
    private String bar;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "my_foreign_key", referencedColumnName = "external_pk")
    private AnotherEntity anotherEntity;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class MyIdClass implements Serializable {

    private String foo;
    private String bar;
}
@Entity
@Table(name = "anotherentity")
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class AnotherEntity {

    @Id
    @Column(name = "external_pk", nullable = false, updatable = false)
    private String externalPk;

    @Column
    private String something;
}

CodePudding user response:

If the oneToOne relation is not optional, you can append the anotation with optional = false, fetch = FetchType.LAZY like such:

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "my_foreign_key", referencedColumnName = "external_pk")
private AnotherEntity anotherEntity;

You'll then be able to access its key with myEntity.getAnotherEntity().getKey() without loading the relation. Here's a POC using hibernate

CodePudding user response:

If you want to be able to access the my_foreign_key foreign key value without having to call MyEntity.getAnotherEntity().getId() and perform a full fetch of anotherEntity, you should probably map it as a read-only basic mapping within the MyEntity instance:

public class MyEntity {
...
    @Column(updatable = false)
    private String bar;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "my_foreign_key", referencedColumnName = "external_pk")
    private AnotherEntity anotherEntity;

    @Column(name = "my_foreign_key",updatable = false, insertable=false)
    private String myForeignKey;
}

As an added benefit, while EclipseLink is pretty good about it on this type of mapping, it can be used in queries to prevent inadvertently forcing a table join unnecessarily. Draw backs though are that you must set this value from the relationship yourself to keep the value in synch with the relationship value - @MapsId might work, but it is meant for relationships involved in ID mappings, so might not be portable.

  • Related