Query Building
PojoQuery provides a fluent API for building and customizing queries. This page covers the various ways to build and modify queries.
Basic Query Building
Creating a Query
The basic way to create a query is using PojoQuery.build():
// Simple query
List<User> users = PojoQuery.build(User.class)
    .execute(dataSource);
// Query with conditions
Article article = PojoQuery.build(Article.class)
    .addWhere("article.id=?", articleId)
    .execute(dataSource)
    .get(0);Adding Conditions
Use addWhere() to add conditions to your query:
List<Article> articles = PojoQuery.build(Article.class)
    .addWhere("article.status = ?", "PUBLISHED")
    .addWhere("article.publishDate > ?", startDate)
    .execute(dataSource);Ordering Results
Use addOrderBy() to sort results:
List<Article> articles = PojoQuery.build(Article.class)
    .addOrderBy("article.publishDate DESC")
    .addOrderBy("article.title ASC")
    .execute(dataSource);Limiting Results
Use setLimit() to restrict the number of results:
// Get first 10 results
List<Article> articles = PojoQuery.build(Article.class)
    .setLimit(10)
    .execute(dataSource);
// Get results 11-20 (pagination)
List<Article> articles = PojoQuery.build(Article.class)
    .setLimit(10, 20)
    .execute(dataSource);Advanced Query Building
Custom Joins
Add custom joins using addJoin():
List<Article> articles = PojoQuery.build(Article.class)
    .addJoin(JoinType.LEFT, "category", "cat",
        "article.category_id=cat.id")
    .addWhere("cat.name = ?", categoryName)
    .execute(dataSource);Group By
Add grouping using addGroupBy():
class ArticleSummary {
    @Id
    Long id;
    String title;
    @Select("COUNT(*)")
    Integer commentCount;
}
List<ArticleSummary> summaries = PojoQuery.build(ArticleSummary.class)
    .addGroupBy("article.id")
    .execute(dataSource);Query Execution
Basic Execution
Execute queries using execute():
// Using DataSource
List<User> users = PojoQuery.build(User.class)
    .execute(dataSource);
// Using Connection
List<User> users = PojoQuery.build(User.class)
    .execute(connection);Query Customization
Custom DbContext
Use a custom DbContext for database-specific settings:
DbContext context = new DbContext() {
    @Override
    public QuoteStyle getQuoteStyle() {
        return QuoteStyle.ANSI;
    }
};
List<User> users = PojoQuery.build(context, User.class)
    .execute(dataSource);DbContextBuilder
The DbContextBuilder provides a fluent API for configuring a DbContext with custom settings. This is the recommended way to create a custom DbContext:
// Create a DbContext with custom settings
DbContext context = DbContext.builder()
    .withQuoteStyle(QuoteStyle.ANSI)    // Use ANSI quotes (") instead of MySQL backticks
    .withQuotedObjectNames(false)       // Don't quote table and column names
    .build();
// Use the configured context
List<User> users = PojoQuery.build(context, User.class)
    .execute(dataSource);Available Configuration Options
- 
withQuoteStyle(QuoteStyle): Set the quote style for database identifiers- 
QuoteStyle.ANSI: Uses double quotes (")
- 
QuoteStyle.MYSQL: Uses backticks (`)
 
- 
- 
withQuotedObjectNames(boolean): Enable or disable quoting of table and column names
- 
withFieldMappingFactory(FieldMappingFactory): Set a custom factory for field mappings
Default Configuration
If no options are specified, the builder creates a DbContext with these defaults:
* MySQL quote style (backticks)
* Object names quoted
* Standard field mapping
Example Configurations
PostgreSQL Configuration
DbContext postgresContext = DbContext.builder()
    .withQuoteStyle(QuoteStyle.ANSI)    // PostgreSQL uses double quotes
    .withQuotedObjectNames(true)        // Always quote identifiers in PostgreSQL
    .build();Best Practices
- 
Use the builder pattern instead of creating a custom DbContextimplementation
- 
Configure the context once and reuse it across queries 
- 
Match the quote style to your database engine 
- 
Consider using custom field mappings for special data types 
- 
Keep the configuration immutable after creation 
Best Practices
Query Building
- 
Use parameterized queries to prevent SQL injection 
- 
Chain methods for readability 
- 
Use appropriate join types 
- 
Consider query performance 
- 
Use streaming for large result sets 
Examples
Complex Query Example
class ArticleSearch {
    @Id
    Long id;
    String title;
    User author;
    Category category;
    @Select("COUNT(DISTINCT comment.id)")
    Integer commentCount;
    @Select("MAX(comment.createdAt)")
    Date lastCommentDate;
}
List<ArticleSearch> results = PojoQuery.build(ArticleSearch.class)
    .addJoin(JoinType.LEFT, "comment", "comment",
        "article.id=comment.article_id")
    .addWhere("article.status = ?", "PUBLISHED")
    .addWhere("article.publishDate BETWEEN ? AND ?",
        startDate, endDate)
    .addWhere("category.name IN (?, ?)",
        "Technology", "Science")
    .addGroupBy("article.id")
    .addOrderBy("commentCount DESC")
    .setLimit(20)
    .execute(dataSource);Pagination Example
class PaginatedQuery<T> {
    private final int pageSize;
    private final int currentPage;
    public PaginatedQuery(int pageSize, int currentPage) {
        this.pageSize = pageSize;
        this.currentPage = currentPage;
    }
    public List<T> execute(PojoQuery<T> query) {
        int offset = (currentPage - 1) * pageSize;
        return query
            .setLimit(offset, pageSize)
            .execute(dataSource);
    }
    public int getTotalCount(PojoQuery<T> query) {
        return query.buildCountStatement()
            .execute(dataSource);
    }
}
// Usage
PaginatedQuery<Article> pagination =
    new PaginatedQuery<>(10, 1);
List<Article> articles = pagination.execute(
    PojoQuery.build(Article.class));
int total = pagination.getTotalCount(
    PojoQuery.build(Article.class));