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

configuration.mddocs/

Configuration and Customization

QueryDSL SQL provides a flexible configuration system for customizing SQL generation, type mappings, naming strategies, schema mappings, and execution monitoring through listeners and custom mappings.

Capabilities

Core Configuration

Central configuration class that coordinates all aspects of QueryDSL SQL behavior.

/**
 * Central configuration class for QueryDSL SQL operations
 */
public class Configuration {
    /**
     * Creates configuration with specified SQL templates
     * @param templates Database-specific SQL templates
     */
    public Configuration(SQLTemplates templates);
    
    /**
     * Gets the SQL templates for this configuration
     * @return SQL templates instance
     */
    public SQLTemplates getTemplates();
    
    /**
     * Registers a custom type for a specific table column
     * @param table Table name
     * @param column Column name
     * @param type Type handler to use
     */
    public void register(String table, String column, Type<?> type);
    
    /**
     * Registers a path mapping for schema and table resolution
     * @param table Table identifier
     * @param property Property name
     * @param path Path to map to
     */
    public void register(String table, String property, Path<?> path);
    
    /**
     * Registers a global type mapping by SQL type name
     * @param typeName SQL type name
     * @param type Type handler to use
     */
    public void registerType(String typeName, Type<?> type);
    
    /**
     * Adds a SQL execution listener
     * @param listener Listener to add
     */
    public void addListener(SQLListener listener);
    
    /**
     * Removes a SQL execution listener
     * @param listener Listener to remove
     */
    public void removeListener(SQLListener listener);
}

Usage Examples:

// Basic configuration setup
SQLTemplates templates = PostgreSQLTemplates.builder().build();
Configuration config = new Configuration(templates);

// Register custom type for specific column
config.register("user", "status", new EnumByNameType<>(UserStatus.class));

// Register global type mapping
config.registerType("uuid", new UtilUUIDType());

// Add execution listener
config.addListener(new SQLBaseListener() {
    @Override
    public void notifyQuery(SQLListenerContext context) {
        logger.info("Executing query: {}", context.getSQL());
    }
});

// Create query factory with configuration
SQLQueryFactory queryFactory = new SQLQueryFactory(config, dataSource);

Type Registration

System for registering and managing custom type mappings at various scopes.

/**
 * JDBC to Java type mapping registry
 */
public class JDBCTypeMapping {
    /**
     * Registers a type for specific JDBC type codes
     * @param type Type handler to register
     * @param jdbcTypes JDBC type codes this handler supports
     */
    public void register(Type<?> type, int... jdbcTypes);
    
    /**
     * Gets registered type for JDBC type code
     * @param jdbcType JDBC type code
     * @param typeName SQL type name
     * @param size Column size
     * @param digits Decimal digits
     * @return Appropriate type handler
     */
    public Type<?> getType(int jdbcType, String typeName, int size, int digits);
}

/**
 * Java class to QueryDSL type mapping registry
 */
public class JavaTypeMapping {
    /**
     * Registers a type handler for a Java class
     * @param javaType Java class
     * @param type Type handler
     */
    public void register(Class<?> javaType, Type<?> type);
    
    /**
     * Gets type handler for Java class
     * @param javaType Java class to get handler for
     * @return Type handler or null if not registered
     */
    public Type<?> getType(Class<?> javaType);
}

Usage Examples:

Configuration config = new Configuration(templates);

// Register type for specific JDBC types
JDBCTypeMapping jdbcMapping = config.getJDBCTypeMapping();
jdbcMapping.register(new UUIDType(), Types.OTHER, Types.VARCHAR);

// Register type for Java classes
JavaTypeMapping javaMapping = config.getJavaTypeMapping();
javaMapping.register(Money.class, new MoneyType());
javaMapping.register(PhoneNumber.class, new PhoneNumberType());

// Column-specific type registration takes precedence
config.register("user", "phone", new InternationalPhoneType());

Name Mapping

Flexible naming strategies for mapping between Java identifiers and SQL identifiers.

/**
 * Interface for mapping between Java and SQL identifiers
 */
public interface NameMapping {
    /**
     * Maps Java identifier to SQL identifier
     * @param javaIdentifier Java field/property name
     * @return SQL column/table name
     */
    String getColumnOverride(String javaIdentifier);
    
    /**
     * Maps SQL identifier to Java identifier
     * @param sqlIdentifier SQL column/table name
     * @return Java field/property name
     */
    String getPropertyOverride(String sqlIdentifier);
}

/**
 * Chains multiple name mappings together
 */
public class ChainedNameMapping implements NameMapping {
    public ChainedNameMapping(NameMapping... mappings);
    public ChainedNameMapping add(NameMapping mapping);
}

/**
 * Changes letter case of identifiers
 */
public class ChangeLetterCaseNameMapping implements NameMapping {
    public enum LetterCase { UPPER, LOWER }
    
    public ChangeLetterCaseNameMapping(LetterCase letterCase);
    public ChangeLetterCaseNameMapping(LetterCase columnCase, LetterCase propertyCase);
}

/**
 * Pre-configured mappings for specific naming conventions
 */
public class PreConfiguredNameMapping implements NameMapping {
    public static final NameMapping CAMEL_CASE_TO_LOWER_WITH_UNDERSCORES;
    public static final NameMapping UPPER_WITH_UNDERSCORES_TO_CAMEL_CASE;
    
    public PreConfiguredNameMapping(Map<String, String> columnToProperty);
}

Usage Examples:

// Configure camelCase to snake_case mapping
NameMapping nameMapping = PreConfiguredNameMapping.CAMEL_CASE_TO_LOWER_WITH_UNDERSCORES;
config.setNameMapping(nameMapping);

// Chain multiple naming strategies
NameMapping chainedMapping = new ChainedNameMapping(
    new ChangeLetterCaseNameMapping(LetterCase.LOWER),
    PreConfiguredNameMapping.CAMEL_CASE_TO_LOWER_WITH_UNDERSCORES
);

// Custom name mapping
Map<String, String> customMappings = new HashMap<>();
customMappings.put("user_id", "userId");
customMappings.put("created_at", "createdTime");
customMappings.put("is_active", "active");

NameMapping customMapping = new PreConfiguredNameMapping(customMappings);
config.setNameMapping(customMapping);

Schema Mapping

Configuration for handling database schemas and table name resolution.

/**
 * Represents schema and table combination
 */
public class SchemaAndTable {
    /**
     * Creates schema and table reference
     * @param schema Schema name (can be null)
     * @param table Table name
     */
    public SchemaAndTable(String schema, String table);
    
    /**
     * Gets the schema name
     * @return Schema name or null
     */
    public String getSchema();
    
    /**
     * Gets the table name
     * @return Table name
     */
    public String getTable();
    
    /**
     * Creates qualified table name
     * @return Schema.table or just table if no schema
     */
    public String getQualifiedName();
}

Usage Examples:

// Configure default schema
Configuration config = new Configuration(templates);
config.setSchema("app_schema");

// Register table with specific schema
config.register(new SchemaAndTable("audit", "user_changes"), qUserAudit);

// Multi-tenant schema mapping
Map<String, String> tenantSchemas = new HashMap<>();
tenantSchemas.put("tenant1", "tenant1_schema");
tenantSchemas.put("tenant2", "tenant2_schema");

// Dynamic schema resolution
String currentTenant = getCurrentTenant();
String schema = tenantSchemas.get(currentTenant);
config.setSchema(schema);

SQL Execution Listeners

Comprehensive listener system for monitoring and customizing SQL execution behavior.

/**
 * Core interface for SQL execution listeners
 */
public interface SQLListener {
    /**
     * Called before query execution
     * @param context Execution context with SQL and parameters
     */
    void notifyQuery(SQLListenerContext context);
    
    /**
     * Called before delete execution
     * @param context Execution context
     */
    void notifyDelete(SQLListenerContext context);
    
    /**
     * Called before insert execution
     * @param context Execution context
     */
    void notifyInsert(SQLListenerContext context);
    
    /**
     * Called before update execution
     * @param context Execution context
     */
    void notifyUpdate(SQLListenerContext context);
    
    /**
     * Called before merge execution
     * @param context Execution context
     */
    void notifyMerge(SQLListenerContext context);
}

/**
 * Extended listener interface with detailed execution information
 */
public interface SQLDetailedListener extends SQLListener {
    /**
     * Called after successful query execution
     * @param context Execution context
     * @param duration Execution duration in milliseconds
     */
    void notifyQueryEnd(SQLListenerContext context, long duration);
    
    /**
     * Called when query execution fails
     * @param context Execution context
     * @param exception Exception that occurred
     */
    void notifyException(SQLListenerContext context, Exception exception);
}

Usage Examples:

// Logging listener
SQLListener loggingListener = new SQLBaseListener() {
    @Override
    public void notifyQuery(SQLListenerContext context) {
        logger.debug("Query: {} with params: {}", 
            context.getSQL(), context.getBindings());
    }
};

// Performance monitoring listener
SQLDetailedListener perfListener = new SQLListenerAdapter() {
    @Override
    public void notifyQueryEnd(SQLListenerContext context, long duration) {
        if (duration > 1000) {  // Log slow queries
            logger.warn("Slow query ({}ms): {}", duration, context.getSQL());
        }
    }
    
    @Override
    public void notifyException(SQLListenerContext context, Exception exception) {
        logger.error("Query failed: {} - {}", context.getSQL(), exception.getMessage());
    }
};

// Add listeners to configuration
config.addListener(loggingListener);
config.addListener(perfListener);

Listener Context and Utilities

Context objects and utilities for working with SQL execution listeners.

/**
 * Execution context provided to listeners
 */
public interface SQLListenerContext {
    /**
     * Gets the SQL statement being executed
     * @return SQL string with parameter placeholders
     */
    String getSQL();
    
    /**
     * Gets the parameter bindings for the SQL
     * @return List of parameter values in order
     */
    List<Object> getBindings();
    
    /**
     * Gets execution metadata
     * @return Map of metadata key-value pairs
     */
    Map<String, Object> getData();
    
    /**
     * Gets the entity being operated on (for DML operations)
     * @return Entity path or null for queries
     */
    RelationalPath<?> getEntity();
}

/**
 * Manages multiple listeners as a single unit
 */
public class SQLListeners implements SQLDetailedListener {
    /**
     * Creates listener collection from individual listeners
     * @param listeners Individual listener instances
     */
    public SQLListeners(SQLListener... listeners);
    
    /**
     * Adds a listener to the collection
     * @param listener Listener to add
     */
    public void add(SQLListener listener);
    
    /**
     * Removes a listener from the collection
     * @param listener Listener to remove
     */
    public void remove(SQLListener listener);
}

Built-in Listener Implementations

Pre-built listener implementations for common use cases.

/**
 * Base listener implementation with no-op methods
 */
public class SQLBaseListener implements SQLListener {
    // All methods have empty default implementations
}

/**
 * Adapter implementation for selective method overriding
 */
public class SQLListenerAdapter implements SQLDetailedListener {
    // All methods have empty default implementations
}

/**
 * Automatically closes database connections after operations
 */
public class SQLCloseListener implements SQLListener {
    public static final SQLCloseListener DEFAULT = new SQLCloseListener();
    
    @Override
    public void notifyQuery(SQLListenerContext context) {
        // Closes connection if auto-close is enabled
    }
}

/**
 * Listener that doesn't close connections
 */
public class SQLNoCloseListener implements SQLListener {
    public static final SQLNoCloseListener DEFAULT = new SQLNoCloseListener();
    
    // No-op implementation that preserves connections
}

Usage Examples:

// Automatic connection management
config.addListener(SQLCloseListener.DEFAULT);

// Custom composite listener
SQLListeners compositeListener = new SQLListeners(
    new AuditingListener(),
    new CacheClearingListener(),
    new MetricsListener()
);
config.addListener(compositeListener);

// Conditional listener
SQLListener conditionalListener = new SQLBaseListener() {
    @Override
    public void notifyQuery(SQLListenerContext context) {
        if (context.getSQL().contains("SELECT")) {
            queryCache.invalidate(context.getSQL());
        }
    }
};

Configuration Builder Pattern

Builder pattern for constructing complex configurations with multiple customizations.

/**
 * Builder pattern for Configuration construction
 */
public class ConfigurationBuilder {
    /**
     * Sets the SQL templates
     * @param templates Database-specific templates
     * @return Builder for method chaining
     */
    public ConfigurationBuilder templates(SQLTemplates templates);
    
    /**
     * Sets the default schema
     * @param schema Schema name
     * @return Builder for method chaining
     */
    public ConfigurationBuilder schema(String schema);
    
    /**
     * Sets the name mapping strategy
     * @param nameMapping Name mapping implementation
     * @return Builder for method chaining
     */
    public ConfigurationBuilder nameMapping(NameMapping nameMapping);
    
    /**
     * Adds a SQL listener
     * @param listener Listener to add
     * @return Builder for method chaining
     */
    public ConfigurationBuilder listener(SQLListener listener);
    
    /**
     * Registers a custom type
     * @param table Table name
     * @param column Column name
     * @param type Type handler
     * @return Builder for method chaining
     */
    public ConfigurationBuilder register(String table, String column, Type<?> type);
    
    /**
     * Builds the final configuration
     * @return Configured Configuration instance
     */
    public Configuration build();
}

Usage Examples:

// Complex configuration using builder pattern
Configuration config = new ConfigurationBuilder()
    .templates(PostgreSQLTemplates.builder().build())
    .schema("application")
    .nameMapping(PreConfiguredNameMapping.CAMEL_CASE_TO_LOWER_WITH_UNDERSCORES)
    .listener(new AuditingListener())
    .listener(new PerformanceListener())
    .register("user", "status", new EnumByNameType<>(UserStatus.class))
    .register("order", "amount", new MoneyType())
    .build();

SQLQueryFactory queryFactory = new SQLQueryFactory(config, dataSource);

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