public sealed interface ConditionType
Defines a custom condition type that can be used to create complex SQL WHERE clauses that cannot be expressed using the standard Condition API.

Custom conditions are particularly useful for:

  • Subqueries (EXISTS, IN, NOT IN)
  • Complex joins or correlations
  • Database-specific functions or syntax
  • Conditions that require multiple columns or complex value transformations

A ConditionType is created on an EntityType and serves as a named identifier for a custom condition. The actual SQL generation logic is provided via a ConditionString when defining the entity.

 // Define a custom condition type for finding tracks not in a playlist
 interface Track {
     EntityType TYPE = DOMAIN.entityType("music.track");

     Column<Long> ID = TYPE.longColumn("id");
     Column<String> NAME = TYPE.stringColumn("name");

     // Define a custom condition for complex subquery logic
     ConditionType NOT_IN_PLAYLIST = TYPE.conditionType("not_in_playlist");
 }

 // In the entity definition, provide the SQL generation logic
 EntityDefinition track() {
     return Track.TYPE.as(
             Track.ID.as()
                 .primaryKey(),
             Track.NAME.as()
                 .column())
         .condition(Track.NOT_IN_PLAYLIST, (columns, values) ->
             "track.id NOT IN (SELECT track_id FROM playlist_track WHERE playlist_id = ?)")
         .build();
 }

 // Usage - find tracks not in a specific playlist
 Long playlistId = 42L;
 List<Entity> tracks = connection.select(
     Track.NOT_IN_PLAYLIST.get(Playlist.ID, playlistId));

Example with multiple columns:

 // Define a condition that uses multiple columns
 ConditionType OVERLAPPING_DATES = TYPE.conditionType("overlapping_dates");

 // In entity definition
 .condition(Event.OVERLAPPING_DATES, (columns, values) -> {
     return "((start_date <= ? AND end_date >= ?) OR " +
            "(start_date <= ? AND end_date >= ?) OR " +
            "(start_date >= ? AND end_date <= ?))";
 })

 // Usage with multiple column/value pairs
 List<Column<?>> columns = List.of(
     Event.START_DATE, Event.END_DATE,
     Event.START_DATE, Event.END_DATE,
     Event.START_DATE, Event.END_DATE);
 List<Object> values = List.of(
     searchStart, searchStart,
     searchEnd, searchEnd,
     searchStart, searchEnd);

 List<Entity> overlapping = connection.select(
     Event.OVERLAPPING_DATES.get(columns, values));

Example with no columns (using only values):

 // Define a condition that doesn't need column references
 ConditionType WITHIN_RADIUS = TYPE.conditionType("within_radius");

 // In entity definition - values are: latitude, longitude, radius
 .condition(Location.WITHIN_RADIUS, (columns, values) -> {
     return "ST_Distance(coordinates, ST_MakePoint(?, ?)) <= ?";
 })

 // Usage with just values
 List<Entity> nearby = connection.select(
     Location.WITHIN_RADIUS.get(List.of(40.7128, -74.0060, 10.0)));
See Also: