SQL support for Querydsl - enables type-safe SQL query construction in Java
—
QueryDSL SQL provides type-safe Data Manipulation Language operations for INSERT, UPDATE, DELETE, and MERGE operations with support for batch processing, automatic key generation, and object mapping.
Type-safe INSERT operations with support for value binding, column selection, and automatic key generation.
/**
* Creates an INSERT clause for the specified table
* @param path Table to insert into
* @return SQLInsertClause for building INSERT statement
*/
public SQLInsertClause insert(RelationalPath<?> path);
/**
* Sets values for specific columns
* @param path Column path
* @param value Value to insert
* @return Insert clause for method chaining
*/
public <T> SQLInsertClause set(Path<T> path, T value);
/**
* Sets multiple column values from a map
* @param values Map of column paths to values
* @return Insert clause for method chaining
*/
public SQLInsertClause set(Map<Path<?>, ?> values);
/**
* Executes the insert and returns number of affected rows
* @return Number of inserted rows
*/
public long execute();
/**
* Executes insert and returns generated key
* @param path Path to the key column
* @return Generated key value
*/
public <T> T executeWithKey(Path<T> path);Usage Examples:
// Simple insert with individual values
long rowsInserted = queryFactory
.insert(qUser)
.set(qUser.name, "John Doe")
.set(qUser.email, "john@example.com")
.set(qUser.age, 30)
.set(qUser.active, true)
.execute();
// Insert with generated key
Long userId = queryFactory
.insert(qUser)
.set(qUser.name, "Jane Smith")
.set(qUser.email, "jane@example.com")
.executeWithKey(qUser.id);
// Insert from map
Map<Path<?>, Object> values = new HashMap<>();
values.put(qUser.name, "Bob Johnson");
values.put(qUser.email, "bob@example.com");
values.put(qUser.age, 25);
queryFactory
.insert(qUser)
.set(values)
.execute();Efficient batch processing for inserting multiple records in a single database operation.
/**
* Creates a batch insert operation
* @param path Table to insert into
* @return SQLInsertBatch for batch operations
*/
public SQLInsertBatch insert(RelationalPath<?> path);
/**
* Adds a batch entry with specified values
* @param values Map of column paths to values for this batch entry
* @return Batch insert for method chaining
*/
public SQLInsertBatch addBatch(Map<Path<?>, ?> values);
/**
* Executes all batched inserts
* @return Array of affected row counts for each batch
*/
public long[] execute();Usage Examples:
// Batch insert multiple users
SQLInsertBatch batch = queryFactory.insert(qUser);
for (UserDto user : users) {
Map<Path<?>, Object> values = new HashMap<>();
values.put(qUser.name, user.getName());
values.put(qUser.email, user.getEmail());
values.put(qUser.age, user.getAge());
batch.addBatch(values);
}
long[] results = batch.execute();Type-safe UPDATE operations with WHERE conditions and support for conditional updates.
/**
* Creates an UPDATE clause for the specified table
* @param path Table to update
* @return SQLUpdateClause for building UPDATE statement
*/
public SQLUpdateClause update(RelationalPath<?> path);
/**
* Sets a column to a new value
* @param path Column path
* @param value New value
* @return Update clause for method chaining
*/
public <T> SQLUpdateClause set(Path<T> path, T value);
/**
* Sets a column using an expression
* @param path Column path
* @param expression Expression to evaluate for new value
* @return Update clause for method chaining
*/
public <T> SQLUpdateClause set(Path<T> path, Expression<? extends T> expression);
/**
* Adds WHERE conditions to limit which rows are updated
* @param conditions Boolean expressions for filtering
* @return Update clause for method chaining
*/
public SQLUpdateClause where(Predicate... conditions);
/**
* Executes the update and returns number of affected rows
* @return Number of updated rows
*/
public long execute();Usage Examples:
// Simple update with WHERE condition
long updatedRows = queryFactory
.update(qUser)
.set(qUser.lastLogin, LocalDateTime.now())
.where(qUser.id.eq(userId))
.execute();
// Update with expression
queryFactory
.update(qProduct)
.set(qProduct.price, qProduct.price.multiply(1.1))
.where(qProduct.category.eq("electronics"))
.execute();
// Conditional update
queryFactory
.update(qUser)
.set(qUser.status, "INACTIVE")
.set(qUser.deactivatedAt, LocalDateTime.now())
.where(qUser.lastLogin.lt(LocalDateTime.now().minusDays(90))
.and(qUser.status.eq("ACTIVE")))
.execute();Batch processing for multiple UPDATE operations with different conditions and values.
/**
* Creates a batch update operation
* @param path Table to update
* @return SQLUpdateBatch for batch operations
*/
public SQLUpdateBatch update(RelationalPath<?> path);
/**
* Adds a batch entry with specified values and conditions
* @param values Map of column paths to new values
* @param conditions WHERE conditions for this batch entry
* @return Batch update for method chaining
*/
public SQLUpdateBatch addBatch(Map<Path<?>, ?> values, Predicate... conditions);
/**
* Executes all batched updates
* @return Array of affected row counts for each batch
*/
public long[] execute();Type-safe DELETE operations with WHERE conditions for selective row removal.
/**
* Creates a DELETE clause for the specified table
* @param path Table to delete from
* @return SQLDeleteClause for building DELETE statement
*/
public SQLDeleteClause delete(RelationalPath<?> path);
/**
* Adds WHERE conditions to limit which rows are deleted
* @param conditions Boolean expressions for filtering
* @return Delete clause for method chaining
*/
public SQLDeleteClause where(Predicate... conditions);
/**
* Executes the delete and returns number of affected rows
* @return Number of deleted rows
*/
public long execute();Usage Examples:
// Delete with simple condition
long deletedRows = queryFactory
.delete(qUser)
.where(qUser.active.isFalse()
.and(qUser.lastLogin.lt(LocalDateTime.now().minusYears(1))))
.execute();
// Delete with subquery
queryFactory
.delete(qOrder)
.where(qOrder.userId.in(
queryFactory.select(qUser.id)
.from(qUser)
.where(qUser.status.eq("DELETED"))
))
.execute();MERGE (UPSERT) operations for inserting new records or updating existing ones based on key matching.
/**
* Creates a MERGE clause for the specified table
* @param path Table to merge into
* @return SQLMergeClause for building MERGE statement
*/
public SQLMergeClause merge(RelationalPath<?> path);
/**
* Specifies the key columns for matching existing records
* @param paths Key column paths
* @return Merge clause for method chaining
*/
public SQLMergeClause key(Path<?>... paths);
/**
* Sets values for the merge operation
* @param path Column path
* @param value Value to insert or update
* @return Merge clause for method chaining
*/
public <T> SQLMergeClause set(Path<T> path, T value);
/**
* Executes the merge and returns number of affected rows
* @return Number of merged rows
*/
public long execute();Usage Examples:
// MERGE operation with key matching
long mergedRows = queryFactory
.merge(qUser)
.key(qUser.email) // Use email as the key for matching
.set(qUser.name, "John Updated")
.set(qUser.age, 31)
.set(qUser.lastModified, LocalDateTime.now())
.execute();
// MERGE with composite key
queryFactory
.merge(qUserRole)
.key(qUserRole.userId, qUserRole.roleId)
.set(qUserRole.assignedAt, LocalDateTime.now())
.set(qUserRole.assignedBy, currentUserId)
.execute();Automatic mapping between Java objects and database columns using various mapping strategies.
/**
* Interface for mapping objects to column/value pairs
* @param <T> Type of object to map
*/
public interface Mapper<T> {
/**
* Creates a map of column paths to values from an object
* @param relationalPath Table path containing column definitions
* @param object Object to map
* @return Map of column paths to values
*/
Map<Path<?>, Object> createMap(RelationalPath<?> relationalPath, T object);
}
/**
* Default mapper using reflection and naming conventions
*/
public class DefaultMapper<T> implements Mapper<T>;
/**
* Bean mapper using getter/setter methods
*/
public class BeanMapper<T> implements Mapper<T>;
/**
* Annotation-based mapper using @Column annotations
*/
public class AnnotationMapper<T> implements Mapper<T>;Usage Examples:
// Using BeanMapper for automatic object mapping
BeanMapper<User> userMapper = new BeanMapper<>(User.class);
User user = new User();
user.setName("Alice Smith");
user.setEmail("alice@example.com");
user.setAge(28);
// Insert using object mapping
Map<Path<?>, Object> values = userMapper.createMap(qUser, user);
queryFactory
.insert(qUser)
.set(values)
.execute();
// Update using object mapping
user.setAge(29);
user.setLastModified(LocalDateTime.now());
Map<Path<?>, Object> updateValues = userMapper.createMap(qUser, user);
queryFactory
.update(qUser)
.set(updateValues)
.where(qUser.id.eq(user.getId()))
.execute();Utilities for handling DML operation results and managing database state.
/**
* Options for controlling prepared statement behavior
*/
public class StatementOptions {
public StatementOptions fetchSize(int fetchSize);
public StatementOptions queryTimeout(int seconds);
public StatementOptions maxRows(int maxRows);
}
/**
* Contains SQL statement and parameter bindings for logging/debugging
*/
public class SQLBindings {
/**
* Gets the SQL statement with placeholders
* @return SQL string
*/
public String getSQL();
/**
* Gets the parameter bindings in order
* @return List of parameter values
*/
public List<Object> getBindings();
}Usage Examples:
// Configure statement options
StatementOptions options = new StatementOptions()
.fetchSize(1000)
.queryTimeout(30);
// Apply options to query
queryFactory
.selectFrom(qUser)
.configure(options)
.fetch();
// Get SQL bindings for logging
SQLDeleteClause deleteClause = queryFactory
.delete(qUser)
.where(qUser.active.isFalse());
SQLBindings bindings = deleteClause.getSQL();
logger.info("Executing SQL: {} with bindings: {}",
bindings.getSQL(), bindings.getBindings());
long deleted = deleteClause.execute();Install with Tessl CLI
npx tessl i tessl/maven-com-querydsl--querydsl-sql