SQL support for Querydsl - enables type-safe SQL query construction in Java
—
QueryDSL SQL provides a comprehensive type mapping system between Java and SQL types with support for custom types, automatic conversion, and database-specific type handling across 50+ built-in type handlers.
Base interface for all type handlers that define how Java objects are converted to and from SQL values.
/**
* Core interface for type conversion between Java and SQL
* @param <T> Java type being handled
*/
public interface Type<T> {
/**
* Retrieves value from ResultSet and converts to Java type
* @param rs ResultSet containing the data
* @param startIndex Starting column index (1-based)
* @return Converted Java object
* @throws SQLException if database access error occurs
*/
T getValue(ResultSet rs, int startIndex) throws SQLException;
/**
* Sets value in PreparedStatement after converting from Java type
* @param st PreparedStatement to set value in
* @param startIndex Starting parameter index (1-based)
* @param value Java object to convert and set
* @throws SQLException if database access error occurs
*/
void setValue(PreparedStatement st, int startIndex, T value) throws SQLException;
/**
* Gets the JDBC type codes this handler supports
* @return Array of JDBC type constants
*/
int[] getSQLTypes();
/**
* Gets the Java class this type handler manages
* @return Java class
*/
Class<T> getReturnedClass();
/**
* Creates a literal representation for SQL generation
* @param value Java value to convert to SQL literal
* @return SQL literal string
*/
String getLiteral(T value);
}Base implementations providing common functionality for type handlers.
/**
* Abstract base class for all type implementations
* @param <T> Java type being handled
*/
public abstract class AbstractType<T> implements Type<T> {
/**
* Creates type handler for specified Java class
* @param type Java class this handler manages
*/
protected AbstractType(Class<T> type);
/**
* Gets null-safe value from ResultSet
* @param rs ResultSet to read from
* @param startIndex Column index
* @return Value or null if SQL NULL
*/
protected T getNullableValue(ResultSet rs, int startIndex) throws SQLException;
}
/**
* Base class for date/time type handlers
* @param <T> Date/time type
*/
public abstract class AbstractDateTimeType<T> extends AbstractType<T>;
/**
* Base class for JSR-310 (java.time) type handlers
* @param <T> java.time type
*/
public abstract class AbstractJSR310DateTimeType<T> extends AbstractDateTimeType<T>;Type handlers for Java primitive types and their wrapper classes.
/**
* String type handler
*/
public class StringType extends AbstractType<String>;
/**
* String type that handles SQL NULL as empty string
*/
public class StringAsObjectType extends AbstractType<String>;
/**
* Integer type handler
*/
public class IntegerType extends AbstractType<Integer>;
/**
* Long type handler
*/
public class LongType extends AbstractType<Long>;
/**
* Double type handler
*/
public class DoubleType extends AbstractType<Double>;
/**
* Boolean type handler
*/
public class BooleanType extends AbstractType<Boolean>;
/**
* Character type handler
*/
public class CharacterType extends AbstractType<Character>;
/**
* Byte type handler
*/
public class ByteType extends AbstractType<Byte>;
/**
* Short type handler
*/
public class ShortType extends AbstractType<Short>;
/**
* Float type handler
*/
public class FloatType extends AbstractType<Float>;Usage Examples:
// Register custom type in configuration
Configuration config = new Configuration(templates);
config.register(new StringType());
config.register(new IntegerType());
// Type registration is typically automatic for standard types
SQLQueryFactory queryFactory = new SQLQueryFactory(config, dataSource);
// Types are used automatically during query execution
List<String> names = queryFactory
.select(qUser.name) // StringType used automatically
.from(qUser)
.fetch();Specialized type handlers for high-precision numeric types.
/**
* BigDecimal type handler for precise decimal arithmetic
*/
public class BigDecimalType extends AbstractType<BigDecimal>;
/**
* BigDecimal type that maps to DOUBLE SQL type
*/
public class BigDecimalAsDoubleType extends AbstractType<BigDecimal>;
/**
* BigInteger type handler for arbitrary-precision integers
*/
public class BigIntegerType extends AbstractType<BigInteger>;
/**
* BigInteger type that maps to BIGINT SQL type
*/
public class BigIntegerAsLongType extends AbstractType<BigInteger>;Usage Examples:
// Working with high-precision numbers
List<BigDecimal> prices = queryFactory
.select(qProduct.price) // BigDecimalType used for DECIMAL columns
.from(qProduct)
.fetch();
// Custom precision handling
Configuration config = new Configuration(templates);
config.register("product", "price", new BigDecimalType());Type handlers for various date and time representations.
/**
* java.sql.Date type handler
*/
public class DateType extends AbstractDateTimeType<java.sql.Date>;
/**
* java.sql.Time type handler
*/
public class TimeType extends AbstractDateTimeType<java.sql.Time>;
/**
* java.sql.Timestamp type handler
*/
public class TimestampType extends AbstractDateTimeType<java.sql.Timestamp>;
/**
* java.util.Date type handler
*/
public class UtilDateType extends AbstractDateTimeType<java.util.Date>;
/**
* java.util.Calendar type handler
*/
public class CalendarType extends AbstractDateTimeType<Calendar>;Modern Java time API type handlers with timezone support.
/**
* LocalDate type handler
*/
public class JSR310LocalDateType extends AbstractJSR310DateTimeType<LocalDate>;
/**
* LocalTime type handler
*/
public class JSR310LocalTimeType extends AbstractJSR310DateTimeType<LocalTime>;
/**
* LocalDateTime type handler
*/
public class JSR310LocalDateTimeType extends AbstractJSR310DateTimeType<LocalDateTime>;
/**
* OffsetTime type handler with timezone offset
*/
public class JSR310OffsetTimeType extends AbstractJSR310DateTimeType<OffsetTime>;
/**
* OffsetDateTime type handler with timezone offset
*/
public class JSR310OffsetDateTimeType extends AbstractJSR310DateTimeType<OffsetDateTime>;
/**
* ZonedDateTime type handler with full timezone support
*/
public class JSR310ZonedDateTimeType extends AbstractJSR310DateTimeType<ZonedDateTime>;
/**
* Instant type handler for timestamps
*/
public class JSR310InstantType extends AbstractJSR310DateTimeType<Instant>;Usage Examples:
// Modern time API usage
List<LocalDateTime> createdTimes = queryFactory
.select(qOrder.createdAt) // JSR310LocalDateTimeType used automatically
.from(qOrder)
.fetch();
// Timezone-aware queries
List<ZonedDateTime> zonedTimes = queryFactory
.select(qEvent.scheduledAt) // JSR310ZonedDateTimeType for timezone data
.from(qEvent)
.fetch();Type handlers for binary data and large objects.
/**
* byte[] type handler for binary data
*/
public class BytesType extends AbstractType<byte[]>;
/**
* byte[] type handler for LONGVARBINARY columns
*/
public class LongVarBinaryBytesType extends AbstractType<byte[]>;
/**
* java.sql.Blob type handler for binary large objects
*/
public class BlobType extends AbstractType<Blob>;
/**
* java.sql.Clob type handler for character large objects
*/
public class ClobType extends AbstractType<Clob>;
/**
* InputStream type handler for streaming binary data
*/
public class InputStreamType extends AbstractType<InputStream>;Usage Examples:
// Binary data handling
byte[] imageData = queryFactory
.select(qDocument.content) // BytesType for VARBINARY columns
.from(qDocument)
.where(qDocument.id.eq(docId))
.fetchOne();
// Large object streaming
InputStream stream = queryFactory
.select(qDocument.largeContent) // InputStreamType for streaming
.from(qDocument)
.where(qDocument.id.eq(docId))
.fetchOne();Type handlers for Java enums with different storage strategies.
/**
* Enum type handler that stores enum values by name (toString)
* @param <T> Enum type
*/
public class EnumByNameType<T extends Enum<T>> extends AbstractType<T> {
public EnumByNameType(Class<T> enumClass);
}
/**
* Enum type handler that stores enum values by ordinal (int)
* @param <T> Enum type
*/
public class EnumByOrdinalType<T extends Enum<T>> extends AbstractType<T> {
public EnumByOrdinalType(Class<T> enumClass);
}
/**
* Enum type handler that stores enum as generic object
* @param <T> Enum type
*/
public class EnumAsObjectType<T extends Enum<T>> extends AbstractType<T> {
public EnumAsObjectType(Class<T> enumClass);
}Usage Examples:
// Enum by name storage
public enum UserStatus { ACTIVE, INACTIVE, SUSPENDED }
Configuration config = new Configuration(templates);
config.register("user", "status", new EnumByNameType<>(UserStatus.class));
// Enum by ordinal storage (more efficient)
config.register("user", "priority", new EnumByOrdinalType<>(Priority.class));
List<UserStatus> statuses = queryFactory
.select(qUser.status)
.from(qUser)
.fetch();Specialized boolean type handlers for databases that don't have native boolean support.
/**
* Boolean type that stores as 'T'/'F' characters
*/
public class TrueFalseType extends AbstractType<Boolean>;
/**
* Boolean type that stores as 'Y'/'N' characters
*/
public class YesNoType extends AbstractType<Boolean>;
/**
* Boolean type that stores as 1/0 integers
*/
public class NumericBooleanType extends AbstractType<Boolean>;Usage Examples:
// Configure boolean storage for legacy databases
Configuration config = new Configuration(templates);
config.register("user", "active", new YesNoType()); // Store as Y/N
config.register("user", "verified", new TrueFalseType()); // Store as T/F
config.register("user", "premium", new NumericBooleanType()); // Store as 1/0
List<Boolean> activeFlags = queryFactory
.select(qUser.active) // Automatically converts Y/N to Boolean
.from(qUser)
.fetch();Type handler for SQL array types with generic element type support.
/**
* Generic array type handler for SQL ARRAY columns
* @param <T> Element type of the array
*/
public class ArrayType<T> extends AbstractType<T[]> {
/**
* Creates array type handler
* @param elementType Type handler for array elements
* @param javaType Java array class
*/
public ArrayType(Type<T> elementType, Class<T[]> javaType);
}Usage Examples:
// PostgreSQL array support
Configuration config = new Configuration(PostgreSQLTemplates.builder().build());
config.register("user", "tags", new ArrayType<>(new StringType(), String[].class));
// Query array columns
List<String[]> userTags = queryFactory
.select(qUser.tags) // Returns String[] from PostgreSQL text[]
.from(qUser)
.fetch();
// Array operations in queries
List<User> users = queryFactory
.selectFrom(qUser)
.where(qUser.tags.contains("vip")) // PostgreSQL array contains operator
.fetch();Type handlers for specialized data types like UUID, URL, XML, and others.
/**
* java.util.UUID type handler
*/
public class UtilUUIDType extends AbstractType<UUID>;
/**
* java.net.URL type handler
*/
public class URLType extends AbstractType<URL>;
/**
* java.util.Locale type handler
*/
public class LocaleType extends AbstractType<Locale>;
/**
* java.util.Currency type handler
*/
public class CurrencyType extends AbstractType<Currency>;
/**
* java.sql.SQLXML type handler
*/
public class SQLXMLType extends AbstractType<SQLXML>;
/**
* XML data stored as String
*/
public class XMLAsStringType extends AbstractType<String>;
/**
* Generic Object type handler
*/
public class ObjectType extends AbstractType<Object>;Usage Examples:
// UUID primary keys
Configuration config = new Configuration(templates);
config.register("user", "id", new UtilUUIDType());
List<UUID> userIds = queryFactory
.select(qUser.id) // UUID type conversion
.from(qUser)
.fetch();
// XML data handling
config.register("document", "content", new XMLAsStringType());
List<String> xmlContent = queryFactory
.select(qDocument.content) // XML stored as String
.from(qDocument)
.fetch();Framework for creating custom type handlers for application-specific data types.
/**
* Interface for null value representation in type system
*/
public class Null {
public static final Object DEFAULT = new Object();
}
/**
* Base class for creating custom type handlers
* @param <T> Java type to handle
*/
public abstract class AbstractType<T> implements Type<T> {
/**
* Template method for handling null values
* @param rs ResultSet to read from
* @param startIndex Column index
* @return Null-safe value
*/
protected T getNullableValue(ResultSet rs, int startIndex) throws SQLException;
/**
* Template method for setting null values
* @param st PreparedStatement to write to
* @param startIndex Parameter index
* @param value Value to set (may be null)
*/
protected void setNullableValue(PreparedStatement st, int startIndex, T value) throws SQLException;
}Usage Examples:
// Custom type for application-specific data
public class MoneyType extends AbstractType<Money> {
public MoneyType() {
super(Money.class);
}
@Override
public Money getValue(ResultSet rs, int startIndex) throws SQLException {
BigDecimal amount = rs.getBigDecimal(startIndex);
String currency = rs.getString(startIndex + 1);
return amount != null ? new Money(amount, currency) : null;
}
@Override
public void setValue(PreparedStatement st, int startIndex, Money value) throws SQLException {
if (value != null) {
st.setBigDecimal(startIndex, value.getAmount());
st.setString(startIndex + 1, value.getCurrency());
} else {
st.setNull(startIndex, Types.DECIMAL);
st.setNull(startIndex + 1, Types.VARCHAR);
}
}
@Override
public int[] getSQLTypes() {
return new int[] { Types.DECIMAL, Types.VARCHAR };
}
}
// Register custom type
Configuration config = new Configuration(templates);
config.register("order", "total", new MoneyType());
// Use custom type in queries
List<Money> orderTotals = queryFactory
.select(qOrder.total) // MoneyType handles conversion automatically
.from(qOrder)
.fetch();Install with Tessl CLI
npx tessl i tessl/maven-com-querydsl--querydsl-sql