CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-querydsl--querydsl-sql

SQL support for Querydsl - enables type-safe SQL query construction in Java

Pending
Overview
Eval results
Files

sql-expressions.mddocs/

SQL Expressions and Functions

QueryDSL SQL provides a comprehensive expression builder for SQL functions, operators, database-specific features, and advanced SQL constructs including window functions, aggregate functions, and conditional expressions.

Capabilities

Core Expression Factory

Central factory class for creating SQL expressions, functions, and operators.

/**
 * Factory class for SQL expressions and functions
 */
public class SQLExpressions {
    /**
     * Creates a constant expression with the specified value
     * @param value Constant value
     * @return Expression representing the constant
     */
    public static <T> SimpleExpression<T> constant(T value);
    
    /**
     * Creates a case expression builder
     * @return CaseBuilder for constructing CASE statements
     */
    public static CaseBuilder cases();
    
    /**
     * Creates a SQL fragment expression
     * @param sql Raw SQL fragment
     * @param args Arguments for the SQL fragment
     * @return Expression wrapping the SQL fragment
     */
    public static SimpleExpression<Object> template(String sql, Object... args);
    
    /**
     * Creates a parameterized SQL template
     * @param type Return type of the expression
     * @param template SQL template with placeholders
     * @param args Template arguments
     * @return Typed expression from template
     */
    public static <T> SimpleExpression<T> template(Class<? extends T> type, String template, Object... args);
}

Usage Examples:

// Constant expressions
Expression<String> statusConstant = SQLExpressions.constant("ACTIVE");
Expression<Integer> zeroConstant = SQLExpressions.constant(0);

// SQL templates for database-specific features
Expression<Integer> customFunction = SQLExpressions.template(Integer.class, 
    "my_custom_function({0}, {1})", qUser.id, qUser.name);

// Case expressions
Expression<String> statusLabel = SQLExpressions.cases()
    .when(qUser.active.isTrue()).then("Active")
    .when(qUser.suspended.isTrue()).then("Suspended")
    .otherwise("Inactive");

String Functions

SQL string manipulation functions with type-safe expression building.

/**
 * String concatenation function
 * @param args String expressions to concatenate
 * @return String expression for concatenated result
 */
public static StringExpression concat(Expression<String>... args);

/**
 * String length function
 * @param str String expression
 * @return Integer expression for string length
 */
public static NumberExpression<Integer> length(Expression<String> str);

/**
 * Substring function
 * @param str Source string expression
 * @param start Starting position (1-based)
 * @param length Length of substring
 * @return String expression for substring result
 */
public static StringExpression substring(Expression<String> str, int start, int length);

/**
 * String trimming function
 * @param str String expression to trim
 * @return String expression with whitespace removed
 */
public static StringExpression trim(Expression<String> str);

/**
 * Converts string to uppercase
 * @param str String expression
 * @return Uppercase string expression
 */
public static StringExpression upper(Expression<String> str);

/**
 * Converts string to lowercase
 * @param str String expression
 * @return Lowercase string expression
 */
public static StringExpression lower(Expression<String> str);

Usage Examples:

// String concatenation
StringExpression fullName = SQLExpressions.concat(qUser.firstName, 
    SQLExpressions.constant(" "), qUser.lastName);

// String manipulation in queries
List<Tuple> results = queryFactory
    .select(qUser.name, 
        SQLExpressions.upper(qUser.name).as("upper_name"),
        SQLExpressions.length(qUser.email).as("email_length"))
    .from(qUser)
    .fetch();

// Substring operations
List<String> areaCodes = queryFactory
    .select(SQLExpressions.substring(qUser.phone, 1, 3))
    .from(qUser)
    .where(qUser.phone.isNotNull())
    .fetch();

Numeric Functions

Mathematical functions and numeric operations for calculations.

/**
 * Absolute value function
 * @param number Numeric expression
 * @return Numeric expression for absolute value
 */
public static <T extends Number & Comparable<T>> NumberExpression<T> abs(Expression<T> number);

/**
 * Ceiling function (round up)
 * @param number Numeric expression
 * @return Numeric expression rounded up to nearest integer
 */
public static NumberExpression<Double> ceil(Expression<? extends Number> number);

/**
 * Floor function (round down)
 * @param number Numeric expression
 * @return Numeric expression rounded down to nearest integer
 */
public static NumberExpression<Double> floor(Expression<? extends Number> number);

/**
 * Round function
 * @param number Numeric expression to round
 * @param precision Number of decimal places
 * @return Rounded numeric expression
 */
public static NumberExpression<Double> round(Expression<? extends Number> number, int precision);

/**
 * Square root function
 * @param number Numeric expression
 * @return Square root expression
 */
public static NumberExpression<Double> sqrt(Expression<? extends Number> number);

/**
 * Power function
 * @param base Base expression
 * @param exponent Exponent expression
 * @return Power expression
 */
public static NumberExpression<Double> power(Expression<? extends Number> base, 
                                           Expression<? extends Number> exponent);

Usage Examples:

// Mathematical calculations
List<Tuple> calculations = queryFactory
    .select(qOrder.amount,
        SQLExpressions.abs(qOrder.amount.subtract(qOrder.discount)).as("net_amount"),
        SQLExpressions.round(qOrder.amount.multiply(0.1), 2).as("tax"),
        SQLExpressions.sqrt(qOrder.quantity).as("sqrt_qty"))
    .from(qOrder)
    .fetch();

// Price calculations with rounding
NumberExpression<Double> finalPrice = SQLExpressions.round(
    qProduct.price.multiply(1.0 - qDiscount.percentage.divide(100.0)), 2);

Date and Time Functions

Date and time manipulation functions for temporal operations.

/**
 * Current timestamp function
 * @return Expression for current database timestamp
 */
public static DateTimeExpression<Date> currentTimestamp();

/**
 * Current date function
 * @return Expression for current database date
 */
public static DateExpression<Date> currentDate();

/**
 * Current time function
 * @return Expression for current database time
 */
public static TimeExpression<Time> currentTime();

/**
 * Date addition function
 * @param date Date expression
 * @param interval Interval to add
 * @param part Date part to add (day, month, year, etc.)
 * @return Date expression with added interval
 */
public static DateTimeExpression<Date> dateAdd(Expression<Date> date, int interval, DatePart part);

/**
 * Date difference function
 * @param date1 First date expression
 * @param date2 Second date expression
 * @param part Date part for difference calculation
 * @return Integer expression for date difference
 */
public static NumberExpression<Integer> dateDiff(DatePart part, 
                                               Expression<Date> date1, 
                                               Expression<Date> date2);

/**
 * Extract date part function
 * @param part Date part to extract
 * @param date Date expression
 * @return Integer expression for extracted part
 */
public static NumberExpression<Integer> extract(DatePart part, Expression<Date> date);

Usage Examples:

// Current timestamp operations
List<User> recentUsers = queryFactory
    .selectFrom(qUser)
    .where(qUser.createdAt.gt(SQLExpressions.dateAdd(
        SQLExpressions.currentTimestamp(), -7, DatePart.day)))
    .fetch();

// Date calculations
List<Tuple> ageCalculations = queryFactory
    .select(qUser.name,
        SQLExpressions.dateDiff(DatePart.year, qUser.birthDate, 
            SQLExpressions.currentDate()).as("age"),
        SQLExpressions.extract(DatePart.month, qUser.birthDate).as("birth_month"))
    .from(qUser)
    .fetch();

// Date formatting and extraction
List<Integer> birthYears = queryFactory
    .select(SQLExpressions.extract(DatePart.year, qUser.birthDate))
    .from(qUser)
    .distinct()
    .orderBy(SQLExpressions.extract(DatePart.year, qUser.birthDate).asc())
    .fetch();

Aggregate Functions

SQL aggregate functions for data summarization and statistical operations.

/**
 * Count function
 * @param expr Expression to count (use * for row count)
 * @return Count expression
 */
public static NumberExpression<Long> count(Expression<?> expr);

/**
 * Count distinct function
 * @param expr Expression to count distinct values
 * @return Count distinct expression
 */
public static NumberExpression<Long> countDistinct(Expression<?> expr);

/**
 * Sum function
 * @param expr Numeric expression to sum
 * @return Sum expression
 */
public static <T extends Number> NumberExpression<T> sum(Expression<T> expr);

/**
 * Average function
 * @param expr Numeric expression to average
 * @return Average expression
 */
public static NumberExpression<Double> avg(Expression<? extends Number> expr);

/**
 * Maximum function
 * @param expr Expression to find maximum value
 * @return Maximum expression
 */
public static <T extends Comparable<T>> ComparableExpression<T> max(Expression<T> expr);

/**
 * Minimum function
 * @param expr Expression to find minimum value
 * @return Minimum expression
 */
public static <T extends Comparable<T>> ComparableExpression<T> min(Expression<T> expr);

Usage Examples:

// Basic aggregations
Tuple stats = queryFactory
    .select(SQLExpressions.count(qOrder.id).as("total_orders"),
        SQLExpressions.sum(qOrder.amount).as("total_amount"),
        SQLExpressions.avg(qOrder.amount).as("avg_amount"),
        SQLExpressions.max(qOrder.amount).as("max_amount"),
        SQLExpressions.min(qOrder.createdAt).as("first_order"))
    .from(qOrder)
    .fetchOne();

// Group aggregations
List<Tuple> customerStats = queryFactory
    .select(qOrder.customerId,
        SQLExpressions.count(qOrder.id).as("order_count"),
        SQLExpressions.sum(qOrder.amount).as("total_spent"),
        SQLExpressions.countDistinct(qOrderItem.productId).as("unique_products"))
    .from(qOrder)
    .join(qOrderItem).on(qOrder.id.eq(qOrderItem.orderId))
    .groupBy(qOrder.customerId)
    .fetch();

Window Functions

Advanced SQL window functions for analytical operations and ranking.

/**
 * ROW_NUMBER() window function
 * @return Window function for row numbering
 */
public static WindowFunction<Long> rowNumber();

/**
 * RANK() window function
 * @return Window function for ranking with gaps
 */
public static WindowFunction<Long> rank();

/**
 * DENSE_RANK() window function
 * @return Window function for ranking without gaps
 */
public static WindowFunction<Long> denseRank();

/**
 * LAG() window function - access previous row value
 * @param expr Expression to get previous value of
 * @param offset Number of rows back (default 1)
 * @return Window function for accessing previous row
 */
public static <T> WindowFunction<T> lag(Expression<T> expr, int offset);

/**
 * LEAD() window function - access next row value
 * @param expr Expression to get next value of
 * @param offset Number of rows forward (default 1)
 * @return Window function for accessing next row
 */
public static <T> WindowFunction<T> lead(Expression<T> expr, int offset);

/**
 * FIRST_VALUE() window function
 * @param expr Expression to get first value of
 * @return Window function for first value in partition
 */
public static <T> WindowFunction<T> firstValue(Expression<T> expr);

/**
 * LAST_VALUE() window function
 * @param expr Expression to get last value of
 * @return Window function for last value in partition
 */
public static <T> WindowFunction<T> lastValue(Expression<T> expr);

Usage Examples:

// Row numbering and ranking
List<Tuple> rankedProducts = queryFactory
    .select(qProduct.name, qProduct.price,
        SQLExpressions.rowNumber().over(qProduct.price.desc()).as("price_rank"),
        SQLExpressions.rank().over(qProduct.categoryId.asc(), qProduct.price.desc()).as("category_rank"))
    .from(qProduct)
    .fetch();

// Running calculations with window functions
List<Tuple> runningTotals = queryFactory
    .select(qOrder.date, qOrder.amount,
        SQLExpressions.sum(qOrder.amount).over(qOrder.date.asc()).as("running_total"),
        SQLExpressions.avg(qOrder.amount).over(qOrder.date.asc()).as("running_avg"))
    .from(qOrder)
    .orderBy(qOrder.date.asc())
    .fetch();

// Lag/Lead for comparisons
List<Tuple> priceChanges = queryFactory
    .select(qStockPrice.date, qStockPrice.price,
        SQLExpressions.lag(qStockPrice.price, 1).over(qStockPrice.date.asc()).as("prev_price"),
        SQLExpressions.lead(qStockPrice.price, 1).over(qStockPrice.date.asc()).as("next_price"))
    .from(qStockPrice)
    .where(qStockPrice.symbol.eq("AAPL"))
    .orderBy(qStockPrice.date.asc())
    .fetch();

Conditional Expressions

SQL conditional logic including CASE statements, COALESCE, and NULL handling.

/**
 * COALESCE function - returns first non-null value
 * @param exprs Expressions to evaluate in order
 * @return Expression with first non-null value
 */
public static <T> SimpleExpression<T> coalesce(Expression<T>... exprs);

/**
 * NULLIF function - returns null if expressions are equal
 * @param expr1 First expression
 * @param expr2 Second expression
 * @return Null if equal, otherwise first expression
 */
public static <T> SimpleExpression<T> nullif(Expression<T> expr1, Expression<T> expr2);

/**
 * Creates a CASE expression builder
 * @return CaseBuilder for constructing CASE statements
 */
public static CaseBuilder cases();

/**
 * CASE expression builder interface
 */
public interface CaseBuilder {
    /**
     * Adds a WHEN condition
     * @param condition Boolean condition to test
     * @return Case when builder for specifying result
     */
    CaseWhen when(Predicate condition);
    
    /**
     * Case when builder for specifying THEN result
     */
    interface CaseWhen {
        /**
         * Specifies result when condition is true
         * @param expr Result expression
         * @return Case builder for additional conditions
         */
        <T> CaseBuilder then(Expression<T> expr);
    }
    
    /**
     * Specifies default result for ELSE clause
     * @param expr Default expression
     * @return Final case expression
     */
    <T> SimpleExpression<T> otherwise(Expression<T> expr);
}

Usage Examples:

// CASE expressions for conditional logic
Expression<String> orderStatus = SQLExpressions.cases()
    .when(qOrder.shippedAt.isNotNull()).then("Shipped")
    .when(qOrder.paidAt.isNotNull()).then("Paid")
    .when(qOrder.createdAt.isNotNull()).then("Pending")
    .otherwise("Unknown");

// COALESCE for null handling
Expression<String> displayName = SQLExpressions.coalesce(
    qUser.nickname, qUser.firstName, qUser.username, 
    SQLExpressions.constant("Anonymous"));

// Complex conditional aggregations
Expression<Long> activeOrderCount = SQLExpressions.cases()
    .when(qOrder.status.eq("ACTIVE")).then(1L)
    .otherwise(0L);

List<Tuple> customerSummary = queryFactory
    .select(qCustomer.name,
        SQLExpressions.sum(activeOrderCount).as("active_orders"),
        SQLExpressions.coalesce(SQLExpressions.max(qOrder.amount), 
            SQLExpressions.constant(0.0)).as("max_order"))
    .from(qCustomer)
    .leftJoin(qOrder).on(qCustomer.id.eq(qOrder.customerId))
    .groupBy(qCustomer.id, qCustomer.name)
    .fetch();

Database-Specific Functions

Specialized functions for specific database systems and their unique features.

/**
 * PostgreSQL-specific functions
 */
public class PostgreSQLExpressions {
    /**
     * PostgreSQL array contains operator
     * @param array Array expression
     * @param element Element to check for
     * @return Boolean expression for containment check
     */
    public static BooleanExpression arrayContains(Expression<?> array, Expression<?> element);
    
    /**
     * PostgreSQL JSONB path query
     * @param jsonb JSONB column expression
     * @param path JSON path expression
     * @return Expression for JSONB path result
     */
    public static SimpleExpression<String> jsonbPath(Expression<String> jsonb, String path);
}

/**
 * MySQL-specific functions
 */
public class MySQLExpressions {
    /**
     * MySQL MATCH AGAINST full-text search
     * @param columns Columns to search in
     * @param searchText Search text
     * @return Boolean expression for full-text match
     */
    public static BooleanExpression match(Expression<?>[] columns, String searchText);
}

/**
 * Oracle-specific functions
 */
public class OracleExpressions {
    /**
     * Oracle CONNECT BY hierarchical query
     * @param condition Connect by condition
     * @return Hierarchical query expression
     */
    public static BooleanExpression connectBy(Predicate condition);
    
    /**
     * Oracle ROWNUM pseudo-column
     * @return Row number expression
     */
    public static NumberExpression<Long> rownum();
}

Usage Examples:

// PostgreSQL array operations
List<User> usersWithTag = queryFactory
    .selectFrom(qUser)
    .where(PostgreSQLExpressions.arrayContains(qUser.tags, 
        SQLExpressions.constant("premium")))
    .fetch();

// PostgreSQL JSONB queries
List<String> emailsFromJson = queryFactory
    .select(PostgreSQLExpressions.jsonbPath(qUser.metadata, "$.email"))
    .from(qUser)
    .where(qUser.metadata.isNotNull())
    .fetch();

// MySQL full-text search
List<Article> searchResults = queryFactory
    .selectFrom(qArticle)
    .where(MySQLExpressions.match(
        new Expression<?>[]{qArticle.title, qArticle.content}, 
        "java spring boot"))
    .fetch();

// Oracle hierarchical queries
List<Employee> hierarchy = queryFactory
    .selectFrom(qEmployee)
    .where(OracleExpressions.connectBy(qEmployee.managerId.eq(qEmployee.id)))
    .fetch();

Custom Function Registration

Framework for registering and using custom database functions.

/**
 * Represents a custom SQL function call
 * @param <T> Return type of the function
 */
public class RelationalFunctionCall<T> extends SimpleExpression<T> {
    /**
     * Creates a custom function call
     * @param type Return type
     * @param function Function name
     * @param args Function arguments
     */
    public RelationalFunctionCall(Class<? extends T> type, String function, Expression<?>... args);
}

Usage Examples:

// Custom function registration
public class CustomFunctions {
    public static NumberExpression<Double> calculateDistance(
            NumberExpression<Double> lat1, NumberExpression<Double> lon1,
            NumberExpression<Double> lat2, NumberExpression<Double> lon2) {
        return new RelationalFunctionCall<>(Double.class, "calculate_distance", 
            lat1, lon1, lat2, lon2);
    }
    
    public static StringExpression formatCurrency(NumberExpression<? extends Number> amount, 
                                                StringExpression currencyCode) {
        return new RelationalFunctionCall<>(String.class, "format_currency", 
            amount, currencyCode);
    }
}

// Usage of custom functions
List<Tuple> storeDistances = queryFactory
    .select(qStore.name,
        CustomFunctions.calculateDistance(
            SQLExpressions.constant(40.7128), // NYC latitude
            SQLExpressions.constant(-74.0060), // NYC longitude
            qStore.latitude,
            qStore.longitude).as("distance"))
    .from(qStore)
    .orderBy(CustomFunctions.calculateDistance(
        SQLExpressions.constant(40.7128),
        SQLExpressions.constant(-74.0060),
        qStore.latitude,
        qStore.longitude).asc())
    .fetch();

Install with Tessl CLI

npx tessl i tessl/maven-com-querydsl--querydsl-sql

docs

configuration.md

database-templates.md

dml-operations.md

index.md

query-construction.md

sql-expressions.md

type-system.md

tile.json