Annotation Reference

PojoQuery uses annotations to map POJOs to database structures and customize query generation.

Quick Reference

Annotation Target Purpose

@Table

Class

Maps class to database table

@Id

Field

Marks primary key field(s)

@FieldName

Field

Custom column name mapping

@Transient

Field

Excludes field from database mapping

@Link

Field

Defines entity relationship (auto JOIN)

@JoinCondition

Field

Custom condition for @Link joins

@Select

Field

Custom SQL expression for field

@Join

Class

Explicit SQL JOIN clause

@Joins

Class

Container for multiple @Join

@GroupBy

Class

Adds GROUP BY clause

@OrderBy

Class

Default ORDER BY clause

@Embedded

Field

Flattens nested object into parent columns

@Other

Field

Maps prefixed columns to Map

@SubClasses

Class

Defines inheritance mapping

@SubClass

Annotation

Subclass discriminator mapping

@NoUpdate

Field

Excludes field from UPDATE statements

Core Mapping Annotations

@Table

Description: Maps a POJO class to a specific database table. Essential for root entities. Target: Class Parameters: value (String, required): The name of the database table. schema (String, optional): The database schema name. Example:

@Table("users") // Maps to 'users' table in the default schema
public class User { ... }

@Table(value="orders", schema="sales") // Maps to 'sales.orders' table
public class Order { ... }

@Id

Description: Marks one or more fields as the primary key component(s) of the entity. Used for findById, updates, and relationship joining by default. Target: Field Example:

@Table("products")
public class Product {
    @Id
    Long productId; // Single primary key
    String name;
}

@Table("order_items")
public class OrderItem {
    @Id Long orderId; // Composite key part 1
    @Id Long itemId;  // Composite key part 2
    int quantity;
}

@FieldName

Description: Specifies the exact database column name for a POJO field when it differs from the field name (or the convention-based name). Target: Field Parameters: * value (String, required): The name of the database column. *Example:

@Table("customers")
public class Customer {
    @Id Long id;
    @FieldName("first_name") String firstName;
    @FieldName("email_addr") String emailAddress;
}

@Transient

Description: Marks a field that should be ignored by PojoQuery during database mapping (SELECT, INSERT, UPDATE). Useful for calculated fields or temporary state. Target: Field Example:

@Table("products")
public class Product {
    @Id Long id;
    BigDecimal price;
    BigDecimal taxRate;

    @Transient
    BigDecimal priceIncludingTax; // Calculated in Java, not stored in DB
}

Relationship Annotations

Description: Explicitly defines a relationship to another entity. For simple relationships following naming conventions (e.g., author field with author_id column), @Link is optional — PojoQuery will infer the join automatically. Use @Link when you need to:

  • Specify a many-to-many relationship with a link table

  • Override the default foreign key column name

  • Fetch simple values from a link table

  • Change the join type (e.g., INNER instead of LEFT)

Target: Field Parameters: linkfield (String, optional): The foreign key column name. * For one-to-one/many-to-one: Column in the current entity’s table referencing the target entity’s ID (Default: {fieldName}_id, e.g., author_id). * For many-to-many: Column in the linktable referencing the current entity’s ID (Default: {currentTableName}_id, e.g., article_id). foreignlinkfield (String, optional): Used only for many-to-many. The foreign key column name in the linktable referencing the target entity’s ID (Default: {fieldName}_id, e.g., tag_id). linktable (String, optional): The name of the intermediate join table for many-to-many relationships. If present, indicates a many-to-many link. (Default: Link.NONE). fetchColumn (String, optional): For collections of simple types (e.g., List<String>, Set<Role>), specifies the column in the linktable holding the collection element values. (Default: Link.NONE). * type (JoinType, optional): The type of join to generate (LEFT, INNER, RIGHT). (Default: JoinType.LEFT). *Examples:

@Table("article")
public class Article {
    @Id Long id;

    // Convention-based joins - @Link is OPTIONAL for these:
    User author;              // Joins on 'author_id' column automatically
    List<Comment> comments;   // Joins on 'article_id' in comment table automatically

    // Many-to-Many: @Link IS REQUIRED with linktable parameter
    @Link(linktable="article_tag", linkfield="article_id", foreignlinkfield="tag_id")
    List<Tag> tags;

    // Collection of Enums: @Link IS REQUIRED with fetchColumn parameter
    @Link(linktable="article_flags", linkfield="article_id", fetchColumn="flag_value")
    Set<ArticleFlag> flags;

    // Non-conventional FK name: @Link IS REQUIRED with linkfield parameter
    @Link(linkfield="writer_id")
    User writer;
}

@JoinCondition

Description: Specifies a custom join condition for a @Link relationship. This is particularly useful when you have multiple relationships to the same table that need to be distinguished by an additional condition (e.g., role-based relationships), or when the default join convention doesn’t apply. Target: Field (used alongside @Link) Parameters: value (String, required): The SQL join condition. Supports placeholders: * {this} - refers to the current entity’s table alias * {linktable} - refers to the link table alias (for many-to-many) * {fieldName} - refers to the target entity’s table alias Examples:

@Table("event")
public class EventWithParticipants {
    @Id Long eventID;
    String title;

    // Multiple relationships to the same 'person' table, distinguished by role
    @Link(linktable="event_person", linkfield="eventID", foreignlinkfield="personID")
    @JoinCondition("{this}.eventID={linktable}.eventID AND {linktable}.role='visitor'")
    List<Person> visitors;

    @Link(linktable="event_person", linkfield="eventID", foreignlinkfield="personID")
    @JoinCondition("{this}.eventID={linktable}.eventID AND {linktable}.role='organizer'")
    List<Person> organizers;
}

@Table("employee")
public class Employee {
    @Id Long id;

    // Custom join condition for one-to-one relationship
    @JoinCondition("{this}.department_id = {department}.id")
    Department department;
}

@Table("festival")
public class Festival {
    @Id Long festivalId;
    String name;

    // Join condition on a collection without @Link
    @JoinCondition("{events}.festivalId = {this}.festivalId")
    List<Event> events;
}

Query Customization Annotations

@Select

Description: Specifies a custom SQL expression or function call to populate a field. The result of the expression will be mapped to this field. Target: Field Parameters: * value (String, required): The SQL expression. Use database-specific syntax. *Example:

@Table("users")
public class UserStats {
    @Id Long id;
    @FieldName("first_name") String firstName;
    @FieldName("last_name") String lastName;

    @Select("CONCAT(first_name, ' ', last_name)") // Database CONCAT function
    String fullName;

    @Select("YEAR(registration_date)") // Database YEAR function
    Integer registrationYear;
}

@Join

Description: Adds a custom, explicit SQL JOIN clause to the query for this entity. Can be used instead of or alongside @Link. Target: Class Parameters: value (String, required if other parameters are not set): The full SQL JOIN clause (e.g., "LEFT JOIN user u ON a.user_id = u.id"). type (JoinType, optional): The join type (LEFT, INNER, RIGHT). schemaName (String, optional): Schema of the table to join. tableName (String, optional): Name of the table to join. alias (String, optional): Alias for the joined table. joinCondition (String, optional): The ON condition for the join. Example:

@Table("article")
// Add a specific join manually
@Join("LEFT JOIN user_profile p ON article.author_id = p.user_id AND p.active = true")
public class ArticleWithProfile {
    @Id Long id;
    // ... other fields
    // You might need @Select or @FieldName to map fields from 'p' if not using @Link
}

@Joins

Description: Container annotation to allow multiple @Join annotations on a single class. Target: Class Parameters: * value (Join[], required): An array of @Join annotations. *Example:

@Table("order")
@Joins({
    @Join("LEFT JOIN customer c ON order.customer_id = c.id"),
    @Join("LEFT JOIN address shipping ON order.shipping_address_id = shipping.id")
})
public class OrderDetails { ... }

@GroupBy

Description: Adds a GROUP BY clause to the generated SQL query. Typically used with @Select annotations containing aggregate functions. Target: Class Parameters: * value (String[], required): An array of SQL expressions to group by (e.g., {"article.id", "author.id"}). *Example:

@Table("comment")
@GroupBy("comment.article_id") // Group comments by article
public class ArticleCommentSummary {
    @FieldName("article_id") Long articleId;

    @Select("COUNT(*)")
    Integer commentCount;

    @Select("MAX(submitdate)")
    Date lastCommentDate;
}

@OrderBy

Description: Adds an ORDER BY clause to the generated SQL query for default sorting. Target: Class Parameters: * value (String, required): The SQL ORDER BY expression (e.g., "publishDate DESC, title ASC"). *Example:

@Table("products")
@OrderBy("category ASC, price DESC")
public class Product { ... }

Advanced Mapping Annotations

@Embedded

Description: Maps fields from a nested Java object (which is not an entity itself) into columns of the parent entity’s table. Flattens the structure. Target: Field Parameters: * prefix (String, optional): A prefix to be added to the column names generated from the embedded object’s fields. (Default: {fieldName}_, e.g., address_). *Example:

@Table("users")
public class User {
    @Id Long id;
    @Embedded(prefix = "ship_") // Columns: ship_street, ship_city, ship_zip
    Address shippingAddress;
}

// Address is NOT an entity, just a value object
public class Address {
    String street;
    String city;
    String zip;
}

@Other

Description: Maps multiple database columns starting with a specific prefix into a single Map<String, Object> field. Useful for dynamic or EAV-like structures. Target: Field Parameters: * prefix (String, required): The prefix identifying columns that belong to this map. The map keys will be the column names *without the prefix. Example:

@Table("settings")
public class UserSettings {
    @Id Long userId;
    // Maps columns like 'pref_theme', 'pref_language' into the map
    // Map keys will be 'theme', 'language'
    @Other(prefix="pref_")
    Map<String, Object> preferences;
}

@SubClasses

Description: Defines an inheritance mapping strategy (currently supports single-table inheritance) for a base class. Used in conjunction with @SubClass. Target: Class (on the base class) Parameters: value (SubClass[], required): An array of @SubClass annotations defining the subclasses. discriminator (String, required): The name of the database column that holds the value identifying the specific subclass. Example: (See @SubClass)

@SubClass

Description: Defines a specific subclass within an inheritance hierarchy declared by @SubClasses. Target: Annotation (used within @SubClasses) Parameters: value (Class<?>, required): The subclass Class object (e.g., Employee.class). discriminatorValue (String, required): The value in the discriminator column that identifies rows belonging to this subclass. Example:

@Table("person") // Base table contains all columns
@SubClasses(
    discriminator = "person_type", // Column indicating the type
    value = {
        @SubClass(value = Employee.class, discriminatorValue = "EMP"),
        @SubClass(value = Customer.class, discriminatorValue = "CUST")
    }
)
public abstract class Person {
    @Id Long id;
    String name;
    @FieldName("person_type") String type; // Mapped discriminator field
}

// Employee specific fields (columns must exist in 'person' table)
public class Employee extends Person {
    String department;
    BigDecimal salary;
}

// Customer specific fields (columns must exist in 'person' table)
public class Customer extends Person {
    Integer loyaltyPoints;
}

@NoUpdate

Description: Marks a field that should not be included in UPDATE statements generated by PojoQuery.update(). Useful for created timestamps or immutable fields. Target: Field Example:

@Table("records")
public class Record {
    @Id Long id;
    String data;
    @NoUpdate // This field will not be updated
    LocalDateTime createdAt;
}