The EntityQueryModel manages how entities are fetched from the database for table models. It provides fine-grained control over query conditions, result limits, ordering, and custom data sources.

1. Overview

EntityQueryModel acts as the data retrieval engine for EntityTableModel, encapsulating:

  • Query conditions (WHERE and HAVING clauses)

  • Result limits to prevent excessive data loading

  • Custom ordering specifications

  • Attribute selection for optimization

  • Custom data sources for specialized queries

    SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
    SwingEntityTableModel tableModel = customerModel.tableModel();
    EntityQueryModel query = tableModel.query();

    // Configure query behavior
    query.limit().set(200);
    query.conditionRequired().set(true);
    query.orderBy().set(OrderBy.ascending(Customer.LASTNAME));

2. Condition Management

2.1. Entity Condition Model

The primary condition mechanism is the EntityConditionModel, which provides a flexible way to build complex queries:

    SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
    EntityConditionModel condition = customerModel.tableModel().query().condition();

    // Set condition values
    condition.get(Customer.EMAIL).set().isNotNull();
    condition.get(Customer.COUNTRY).set().equalTo("Iceland");

    // The resulting query will include:
    // WHERE email is not null AND country = 'Iceland'

2.2. Additional Conditions

Beyond the table condition model, you can add custom WHERE and/or HAVING conditions:

    SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
    AdditionalConditions additional = customerModel.tableModel().query().condition().additional();

    // Single additional condition
    additional.where().set(() -> Customer.COUNTRY.equalTo("Iceland"));

    // Multiple conditions with custom conjunction
    additional.where().set(() -> Condition.or(
            Customer.CITY.equalTo("Reykjavik"),
            Customer.CITY.equalTo("Akureyri")
    ));

3. Query Limits

Prevent loading excessive data by setting query limits:

    SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
    EntityQueryModel query = customerModel.tableModel().query();

    // Set a specific limit
    query.limit().set(500);

    // Resets to the default limit specified by the
    // EntityQueryModel.LIMIT configuration setting,
    // if one is specified, otherwise clears the
    // limit and allows fetching of all matching rows
    query.limit().clear();

    // Add a max limit validator
    query.limit().addValidator(newLimit -> {
      if (newLimit > 10.000) {
        throw new IllegalArgumentException("Limit may not exceed 10.000");
      }
    });

    // Listen for limit changes
    query.limit().addConsumer(newLimit ->
            System.out.println("Query limit changed to: " + newLimit));

4. Result Ordering

Specify how results should be ordered:

    SwingEntityModel invoiceModel = new SwingEntityModel(Invoice.TYPE, connectionProvider);
    EntityQueryModel query = invoiceModel.tableModel().query();

    // Single column ordering
    query.orderBy().set(OrderBy.descending(Invoice.DATE));

    // Multiple columns
    query.orderBy().set(OrderBy.builder()
            .ascending(Invoice.BILLINGCOUNTRY)
            .descending(Invoice.DATE)
            .build()
    );

5. Custom Data Sources

For complex queries that can’t be expressed through conditions, provide a custom data source:

    SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);

    customerModel.tableModel().query().dataSource().set(query -> {
      EntityConnection connection = query.connectionProvider().connection();

      // Custom query with complex joins or database-specific features
      return connection.select(Select.where(customComplexCondition())
              .attributes(Customer.ADDRESS, Customer.CITY, Customer.COUNTRY)
              .build());
    });

6. Condition Required

Prevent accidental full table scans:

    SwingEntityModel customerModel = new SwingEntityModel(Customer.TYPE, connectionProvider);
    EntityQueryModel query = customerModel.tableModel().query();

    // Require at least one condition
    query.conditionRequired().set(true);

    // Specify that a certain condition must be enabled
    query.conditionEnabled().set(query.condition().get(Customer.SUPPORTREP_FK).enabled());

7. Attribute Management

Optimize queries by selecting only needed attributes:

    SwingEntityModel albumModel = new SwingEntityModel(Album.TYPE, connectionProvider);
    EntityQueryModel query = albumModel.tableModel().query();

    // Exclude large columns by default
    query.attributes().exclude().add(Album.COVER);

    // Include them only when needed
    State detailView = State.state();
    detailView.addConsumer(showDetails -> {
      if (showDetails) {
        query.attributes().exclude().remove(Album.COVER);
      }
      else {
        query.attributes().exclude().add(Album.COVER);
      }
    });