0
# Type System
1
2
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.
3
4
## Capabilities
5
6
### Core Type Interface
7
8
Base interface for all type handlers that define how Java objects are converted to and from SQL values.
9
10
```java { .api }
11
/**
12
* Core interface for type conversion between Java and SQL
13
* @param <T> Java type being handled
14
*/
15
public interface Type<T> {
16
/**
17
* Retrieves value from ResultSet and converts to Java type
18
* @param rs ResultSet containing the data
19
* @param startIndex Starting column index (1-based)
20
* @return Converted Java object
21
* @throws SQLException if database access error occurs
22
*/
23
T getValue(ResultSet rs, int startIndex) throws SQLException;
24
25
/**
26
* Sets value in PreparedStatement after converting from Java type
27
* @param st PreparedStatement to set value in
28
* @param startIndex Starting parameter index (1-based)
29
* @param value Java object to convert and set
30
* @throws SQLException if database access error occurs
31
*/
32
void setValue(PreparedStatement st, int startIndex, T value) throws SQLException;
33
34
/**
35
* Gets the JDBC type codes this handler supports
36
* @return Array of JDBC type constants
37
*/
38
int[] getSQLTypes();
39
40
/**
41
* Gets the Java class this type handler manages
42
* @return Java class
43
*/
44
Class<T> getReturnedClass();
45
46
/**
47
* Creates a literal representation for SQL generation
48
* @param value Java value to convert to SQL literal
49
* @return SQL literal string
50
*/
51
String getLiteral(T value);
52
}
53
```
54
55
### Abstract Base Types
56
57
Base implementations providing common functionality for type handlers.
58
59
```java { .api }
60
/**
61
* Abstract base class for all type implementations
62
* @param <T> Java type being handled
63
*/
64
public abstract class AbstractType<T> implements Type<T> {
65
/**
66
* Creates type handler for specified Java class
67
* @param type Java class this handler manages
68
*/
69
protected AbstractType(Class<T> type);
70
71
/**
72
* Gets null-safe value from ResultSet
73
* @param rs ResultSet to read from
74
* @param startIndex Column index
75
* @return Value or null if SQL NULL
76
*/
77
protected T getNullableValue(ResultSet rs, int startIndex) throws SQLException;
78
}
79
80
/**
81
* Base class for date/time type handlers
82
* @param <T> Date/time type
83
*/
84
public abstract class AbstractDateTimeType<T> extends AbstractType<T>;
85
86
/**
87
* Base class for JSR-310 (java.time) type handlers
88
* @param <T> java.time type
89
*/
90
public abstract class AbstractJSR310DateTimeType<T> extends AbstractDateTimeType<T>;
91
```
92
93
### Primitive and Basic Types
94
95
Type handlers for Java primitive types and their wrapper classes.
96
97
```java { .api }
98
/**
99
* String type handler
100
*/
101
public class StringType extends AbstractType<String>;
102
103
/**
104
* String type that handles SQL NULL as empty string
105
*/
106
public class StringAsObjectType extends AbstractType<String>;
107
108
/**
109
* Integer type handler
110
*/
111
public class IntegerType extends AbstractType<Integer>;
112
113
/**
114
* Long type handler
115
*/
116
public class LongType extends AbstractType<Long>;
117
118
/**
119
* Double type handler
120
*/
121
public class DoubleType extends AbstractType<Double>;
122
123
/**
124
* Boolean type handler
125
*/
126
public class BooleanType extends AbstractType<Boolean>;
127
128
/**
129
* Character type handler
130
*/
131
public class CharacterType extends AbstractType<Character>;
132
133
/**
134
* Byte type handler
135
*/
136
public class ByteType extends AbstractType<Byte>;
137
138
/**
139
* Short type handler
140
*/
141
public class ShortType extends AbstractType<Short>;
142
143
/**
144
* Float type handler
145
*/
146
public class FloatType extends AbstractType<Float>;
147
```
148
149
**Usage Examples:**
150
151
```java
152
// Register custom type in configuration
153
Configuration config = new Configuration(templates);
154
config.register(new StringType());
155
config.register(new IntegerType());
156
157
// Type registration is typically automatic for standard types
158
SQLQueryFactory queryFactory = new SQLQueryFactory(config, dataSource);
159
160
// Types are used automatically during query execution
161
List<String> names = queryFactory
162
.select(qUser.name) // StringType used automatically
163
.from(qUser)
164
.fetch();
165
```
166
167
### Numeric Types
168
169
Specialized type handlers for high-precision numeric types.
170
171
```java { .api }
172
/**
173
* BigDecimal type handler for precise decimal arithmetic
174
*/
175
public class BigDecimalType extends AbstractType<BigDecimal>;
176
177
/**
178
* BigDecimal type that maps to DOUBLE SQL type
179
*/
180
public class BigDecimalAsDoubleType extends AbstractType<BigDecimal>;
181
182
/**
183
* BigInteger type handler for arbitrary-precision integers
184
*/
185
public class BigIntegerType extends AbstractType<BigInteger>;
186
187
/**
188
* BigInteger type that maps to BIGINT SQL type
189
*/
190
public class BigIntegerAsLongType extends AbstractType<BigInteger>;
191
```
192
193
**Usage Examples:**
194
195
```java
196
// Working with high-precision numbers
197
List<BigDecimal> prices = queryFactory
198
.select(qProduct.price) // BigDecimalType used for DECIMAL columns
199
.from(qProduct)
200
.fetch();
201
202
// Custom precision handling
203
Configuration config = new Configuration(templates);
204
config.register("product", "price", new BigDecimalType());
205
```
206
207
### Date and Time Types
208
209
Type handlers for various date and time representations.
210
211
```java { .api }
212
/**
213
* java.sql.Date type handler
214
*/
215
public class DateType extends AbstractDateTimeType<java.sql.Date>;
216
217
/**
218
* java.sql.Time type handler
219
*/
220
public class TimeType extends AbstractDateTimeType<java.sql.Time>;
221
222
/**
223
* java.sql.Timestamp type handler
224
*/
225
public class TimestampType extends AbstractDateTimeType<java.sql.Timestamp>;
226
227
/**
228
* java.util.Date type handler
229
*/
230
public class UtilDateType extends AbstractDateTimeType<java.util.Date>;
231
232
/**
233
* java.util.Calendar type handler
234
*/
235
public class CalendarType extends AbstractDateTimeType<Calendar>;
236
```
237
238
### JSR-310 (java.time) Types
239
240
Modern Java time API type handlers with timezone support.
241
242
```java { .api }
243
/**
244
* LocalDate type handler
245
*/
246
public class JSR310LocalDateType extends AbstractJSR310DateTimeType<LocalDate>;
247
248
/**
249
* LocalTime type handler
250
*/
251
public class JSR310LocalTimeType extends AbstractJSR310DateTimeType<LocalTime>;
252
253
/**
254
* LocalDateTime type handler
255
*/
256
public class JSR310LocalDateTimeType extends AbstractJSR310DateTimeType<LocalDateTime>;
257
258
/**
259
* OffsetTime type handler with timezone offset
260
*/
261
public class JSR310OffsetTimeType extends AbstractJSR310DateTimeType<OffsetTime>;
262
263
/**
264
* OffsetDateTime type handler with timezone offset
265
*/
266
public class JSR310OffsetDateTimeType extends AbstractJSR310DateTimeType<OffsetDateTime>;
267
268
/**
269
* ZonedDateTime type handler with full timezone support
270
*/
271
public class JSR310ZonedDateTimeType extends AbstractJSR310DateTimeType<ZonedDateTime>;
272
273
/**
274
* Instant type handler for timestamps
275
*/
276
public class JSR310InstantType extends AbstractJSR310DateTimeType<Instant>;
277
```
278
279
**Usage Examples:**
280
281
```java
282
// Modern time API usage
283
List<LocalDateTime> createdTimes = queryFactory
284
.select(qOrder.createdAt) // JSR310LocalDateTimeType used automatically
285
.from(qOrder)
286
.fetch();
287
288
// Timezone-aware queries
289
List<ZonedDateTime> zonedTimes = queryFactory
290
.select(qEvent.scheduledAt) // JSR310ZonedDateTimeType for timezone data
291
.from(qEvent)
292
.fetch();
293
```
294
295
### Binary and LOB Types
296
297
Type handlers for binary data and large objects.
298
299
```java { .api }
300
/**
301
* byte[] type handler for binary data
302
*/
303
public class BytesType extends AbstractType<byte[]>;
304
305
/**
306
* byte[] type handler for LONGVARBINARY columns
307
*/
308
public class LongVarBinaryBytesType extends AbstractType<byte[]>;
309
310
/**
311
* java.sql.Blob type handler for binary large objects
312
*/
313
public class BlobType extends AbstractType<Blob>;
314
315
/**
316
* java.sql.Clob type handler for character large objects
317
*/
318
public class ClobType extends AbstractType<Clob>;
319
320
/**
321
* InputStream type handler for streaming binary data
322
*/
323
public class InputStreamType extends AbstractType<InputStream>;
324
```
325
326
**Usage Examples:**
327
328
```java
329
// Binary data handling
330
byte[] imageData = queryFactory
331
.select(qDocument.content) // BytesType for VARBINARY columns
332
.from(qDocument)
333
.where(qDocument.id.eq(docId))
334
.fetchOne();
335
336
// Large object streaming
337
InputStream stream = queryFactory
338
.select(qDocument.largeContent) // InputStreamType for streaming
339
.from(qDocument)
340
.where(qDocument.id.eq(docId))
341
.fetchOne();
342
```
343
344
### Enum Types
345
346
Type handlers for Java enums with different storage strategies.
347
348
```java { .api }
349
/**
350
* Enum type handler that stores enum values by name (toString)
351
* @param <T> Enum type
352
*/
353
public class EnumByNameType<T extends Enum<T>> extends AbstractType<T> {
354
public EnumByNameType(Class<T> enumClass);
355
}
356
357
/**
358
* Enum type handler that stores enum values by ordinal (int)
359
* @param <T> Enum type
360
*/
361
public class EnumByOrdinalType<T extends Enum<T>> extends AbstractType<T> {
362
public EnumByOrdinalType(Class<T> enumClass);
363
}
364
365
/**
366
* Enum type handler that stores enum as generic object
367
* @param <T> Enum type
368
*/
369
public class EnumAsObjectType<T extends Enum<T>> extends AbstractType<T> {
370
public EnumAsObjectType(Class<T> enumClass);
371
}
372
```
373
374
**Usage Examples:**
375
376
```java
377
// Enum by name storage
378
public enum UserStatus { ACTIVE, INACTIVE, SUSPENDED }
379
380
Configuration config = new Configuration(templates);
381
config.register("user", "status", new EnumByNameType<>(UserStatus.class));
382
383
// Enum by ordinal storage (more efficient)
384
config.register("user", "priority", new EnumByOrdinalType<>(Priority.class));
385
386
List<UserStatus> statuses = queryFactory
387
.select(qUser.status)
388
.from(qUser)
389
.fetch();
390
```
391
392
### Boolean Conversion Types
393
394
Specialized boolean type handlers for databases that don't have native boolean support.
395
396
```java { .api }
397
/**
398
* Boolean type that stores as 'T'/'F' characters
399
*/
400
public class TrueFalseType extends AbstractType<Boolean>;
401
402
/**
403
* Boolean type that stores as 'Y'/'N' characters
404
*/
405
public class YesNoType extends AbstractType<Boolean>;
406
407
/**
408
* Boolean type that stores as 1/0 integers
409
*/
410
public class NumericBooleanType extends AbstractType<Boolean>;
411
```
412
413
**Usage Examples:**
414
415
```java
416
// Configure boolean storage for legacy databases
417
Configuration config = new Configuration(templates);
418
config.register("user", "active", new YesNoType()); // Store as Y/N
419
config.register("user", "verified", new TrueFalseType()); // Store as T/F
420
config.register("user", "premium", new NumericBooleanType()); // Store as 1/0
421
422
List<Boolean> activeFlags = queryFactory
423
.select(qUser.active) // Automatically converts Y/N to Boolean
424
.from(qUser)
425
.fetch();
426
```
427
428
### Array Types
429
430
Type handler for SQL array types with generic element type support.
431
432
```java { .api }
433
/**
434
* Generic array type handler for SQL ARRAY columns
435
* @param <T> Element type of the array
436
*/
437
public class ArrayType<T> extends AbstractType<T[]> {
438
/**
439
* Creates array type handler
440
* @param elementType Type handler for array elements
441
* @param javaType Java array class
442
*/
443
public ArrayType(Type<T> elementType, Class<T[]> javaType);
444
}
445
```
446
447
**Usage Examples:**
448
449
```java
450
// PostgreSQL array support
451
Configuration config = new Configuration(PostgreSQLTemplates.builder().build());
452
config.register("user", "tags", new ArrayType<>(new StringType(), String[].class));
453
454
// Query array columns
455
List<String[]> userTags = queryFactory
456
.select(qUser.tags) // Returns String[] from PostgreSQL text[]
457
.from(qUser)
458
.fetch();
459
460
// Array operations in queries
461
List<User> users = queryFactory
462
.selectFrom(qUser)
463
.where(qUser.tags.contains("vip")) // PostgreSQL array contains operator
464
.fetch();
465
```
466
467
### Specialized Types
468
469
Type handlers for specialized data types like UUID, URL, XML, and others.
470
471
```java { .api }
472
/**
473
* java.util.UUID type handler
474
*/
475
public class UtilUUIDType extends AbstractType<UUID>;
476
477
/**
478
* java.net.URL type handler
479
*/
480
public class URLType extends AbstractType<URL>;
481
482
/**
483
* java.util.Locale type handler
484
*/
485
public class LocaleType extends AbstractType<Locale>;
486
487
/**
488
* java.util.Currency type handler
489
*/
490
public class CurrencyType extends AbstractType<Currency>;
491
492
/**
493
* java.sql.SQLXML type handler
494
*/
495
public class SQLXMLType extends AbstractType<SQLXML>;
496
497
/**
498
* XML data stored as String
499
*/
500
public class XMLAsStringType extends AbstractType<String>;
501
502
/**
503
* Generic Object type handler
504
*/
505
public class ObjectType extends AbstractType<Object>;
506
```
507
508
**Usage Examples:**
509
510
```java
511
// UUID primary keys
512
Configuration config = new Configuration(templates);
513
config.register("user", "id", new UtilUUIDType());
514
515
List<UUID> userIds = queryFactory
516
.select(qUser.id) // UUID type conversion
517
.from(qUser)
518
.fetch();
519
520
// XML data handling
521
config.register("document", "content", new XMLAsStringType());
522
523
List<String> xmlContent = queryFactory
524
.select(qDocument.content) // XML stored as String
525
.from(qDocument)
526
.fetch();
527
```
528
529
### Custom Type Creation
530
531
Framework for creating custom type handlers for application-specific data types.
532
533
```java { .api }
534
/**
535
* Interface for null value representation in type system
536
*/
537
public class Null {
538
public static final Object DEFAULT = new Object();
539
}
540
541
/**
542
* Base class for creating custom type handlers
543
* @param <T> Java type to handle
544
*/
545
public abstract class AbstractType<T> implements Type<T> {
546
/**
547
* Template method for handling null values
548
* @param rs ResultSet to read from
549
* @param startIndex Column index
550
* @return Null-safe value
551
*/
552
protected T getNullableValue(ResultSet rs, int startIndex) throws SQLException;
553
554
/**
555
* Template method for setting null values
556
* @param st PreparedStatement to write to
557
* @param startIndex Parameter index
558
* @param value Value to set (may be null)
559
*/
560
protected void setNullableValue(PreparedStatement st, int startIndex, T value) throws SQLException;
561
}
562
```
563
564
**Usage Examples:**
565
566
```java
567
// Custom type for application-specific data
568
public class MoneyType extends AbstractType<Money> {
569
public MoneyType() {
570
super(Money.class);
571
}
572
573
@Override
574
public Money getValue(ResultSet rs, int startIndex) throws SQLException {
575
BigDecimal amount = rs.getBigDecimal(startIndex);
576
String currency = rs.getString(startIndex + 1);
577
return amount != null ? new Money(amount, currency) : null;
578
}
579
580
@Override
581
public void setValue(PreparedStatement st, int startIndex, Money value) throws SQLException {
582
if (value != null) {
583
st.setBigDecimal(startIndex, value.getAmount());
584
st.setString(startIndex + 1, value.getCurrency());
585
} else {
586
st.setNull(startIndex, Types.DECIMAL);
587
st.setNull(startIndex + 1, Types.VARCHAR);
588
}
589
}
590
591
@Override
592
public int[] getSQLTypes() {
593
return new int[] { Types.DECIMAL, Types.VARCHAR };
594
}
595
}
596
597
// Register custom type
598
Configuration config = new Configuration(templates);
599
config.register("order", "total", new MoneyType());
600
601
// Use custom type in queries
602
List<Money> orderTotals = queryFactory
603
.select(qOrder.total) // MoneyType handles conversion automatically
604
.from(qOrder)
605
.fetch();
606
```