Interface ForeignKeyDefinition

All Superinterfaces:
AttributeDefinition<Entity>

public interface ForeignKeyDefinition extends AttributeDefinition<Entity>
Represents a reference to another entity, typically but not necessarily based on a foreign key.

ForeignKeyDefinition configures how foreign key relationships behave, including reference depth for automatic loading, soft references for logical relationships, and attribute selection for referenced entities.

Foreign key definitions control the loading strategy and behavior of entity relationships:

public class Store extends DefaultDomain {

    interface Customer {
        EntityType TYPE = DOMAIN.entityType("store.customer");
        Column<Integer> ID = TYPE.integerColumn("id");
        Column<String> NAME = TYPE.stringColumn("name");
        Column<String> EMAIL = TYPE.stringColumn("email");
    }

    interface Order {
        EntityType TYPE = DOMAIN.entityType("store.order");
        Column<Integer> ID = TYPE.integerColumn("id");
        Column<Integer> CUSTOMER_ID = TYPE.integerColumn("customer_id");
        Column<LocalDateTime> ORDER_DATE = TYPE.localDateTimeColumn("order_date");
        Column<BigDecimal> TOTAL = TYPE.bigDecimalColumn("total");

        ForeignKey CUSTOMER_FK = TYPE.foreignKey("customer_fk", CUSTOMER_ID, Customer.ID);
    }

    interface OrderLine {
        EntityType TYPE = DOMAIN.entityType("store.order_line");
        Column<Integer> ORDER_ID = TYPE.integerColumn("order_id");
        Column<Integer> PRODUCT_ID = TYPE.integerColumn("product_id");
        Column<Integer> QUANTITY = TYPE.integerColumn("quantity");

        ForeignKey ORDER_FK = TYPE.foreignKey("order_fk", ORDER_ID, Order.ID);
    }

    void defineEntities() {
        Order.TYPE.define(
                Order.ID.define()
                    .primaryKey(),
                Order.CUSTOMER_ID.define()
                    .column(),
                Order.ORDER_DATE.define()
                    .column(),
                Order.TOTAL.define()
                    .column(),

                // Basic foreign key with default reference depth (1)
                Order.CUSTOMER_FK.define()
                    .foreignKey()
                    .caption("Customer"))
            .build();

        OrderLine.TYPE.define(
                OrderLine.ORDER_ID.define()
                    .primaryKey(),
                OrderLine.PRODUCT_ID.define()
                    .column(),
                OrderLine.QUANTITY.define()
                    .column(),

                // Foreign key with deeper reference depth to load customer info
                OrderLine.ORDER_FK.define()
                    .foreignKey()
                    .caption("Order")
                    .referenceDepth(2)  // Load order AND its customer
                    .attributes(Order.ORDER_DATE, Order.TOTAL)) // Only load specific order attributes
            .build();
    }
}

// Reference depth behavior examples:

// Reference depth 0: No automatic loading
List<Entity> orders = connection.select(
    Select.where(all(Order.TYPE))
        .referenceDepth(0)
        .build());

Entity order = orders.get(0);
Entity customer = order.get(Order.CUSTOMER_FK); // null - not loaded
Entity customerEntity = order.entity(Order.CUSTOMER_FK); // Contains only primary key

// Reference depth 1: Load referenced entity only
List<Entity> ordersWithCustomers = connection.select(
    Select.where(all(Order.TYPE))
        .referenceDepth(1) // Default
        .build());

Entity orderWithCustomer = ordersWithCustomers.get(0);
Entity loadedCustomer = orderWithCustomer.get(Order.CUSTOMER_FK); // Fully loaded customer

// Reference depth 2: Load referenced entity and its references
List<Entity> orderLines = connection.select(all(OrderLine.TYPE));

Entity orderLine = orderLines.get(0);
Entity orderWithCustomer = orderLine.get(OrderLine.ORDER_FK); // Order is loaded
Entity customer = orderWithCustomer.get(Order.CUSTOMER_FK);   // Customer is also loaded
See Also:
  • Field Details

    • DEFAULT_FOREIGN_KEY_REFERENCE_DEPTH

      static final int DEFAULT_FOREIGN_KEY_REFERENCE_DEPTH
      The default number of levels of foreign keys to fetch
      See Also:
    • FOREIGN_KEY_REFERENCE_DEPTH

      static final PropertyValue<Integer> FOREIGN_KEY_REFERENCE_DEPTH
      Specifies the default foreign key reference depth
      • Value type: Integer
      • Default value: 1
  • Method Details

    • attribute

      ForeignKey attribute()
      Description copied from interface: AttributeDefinition
      The Attribute this definition is based on, should be unique within an Entity. By default, the Attribute.name() serves as column name for database columns.
      Specified by:
      attribute in interface AttributeDefinition<Entity>
      Returns:
      the foreign key attribute this foreign key is based on.
    • referenceDepth

      int referenceDepth()
      Returns:
      the default query reference depth for this foreign key
    • soft

      boolean soft()
      Returns:
      true if this foreign key is not based on a physical (table) foreign key and should not prevent deletion
    • readOnly

      boolean readOnly(Column<?> referenceColumn)
      Returns true if the given foreign key reference column is read-only, as in, not updated when the foreign key value is set.
      Parameters:
      referenceColumn - the reference column
      Returns:
      true if the given foreign key reference column is read-only
    • references

      List<ForeignKey.Reference<?>> references()
      Returns:
      the ForeignKey.References that comprise this foreign key
    • attributes

      List<Attribute<?>> attributes()
      Returns:
      the attributes to select when fetching entities referenced via this foreign key, an empty list in case of all attributes