Annotation Reference
PojoQuery uses annotations to map POJOs to database structures and customize query generation.
Quick Reference
| Annotation | Target | Purpose |
|---|---|---|
|
Class |
Maps class to database table |
|
Field |
Marks primary key field(s) |
|
Field |
Custom column name mapping |
|
Field |
Excludes field from database mapping |
|
Field |
Defines entity relationship (auto JOIN) |
|
Field |
Custom condition for |
|
Field |
Custom SQL expression for field |
|
Class |
Explicit SQL JOIN clause |
|
Class |
Container for multiple |
|
Class |
Adds GROUP BY clause |
|
Class |
Default ORDER BY clause |
|
Field |
Flattens nested object into parent columns |
|
Field |
Maps prefixed columns to Map |
|
Class |
Defines table-per-subclass inheritance |
|
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
@Link
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 static class EventWithParticipants {
@Id Long id;
String title;
@Link(linktable = "event_person", linkfield = "event_id", foreignlinkfield = "person_id")
@JoinCondition("{this}.id = {linktable}.event_id AND {linktable}.role = 'visitor'")
List<Person> visitors;
@Link(linktable = "event_person", linkfield = "event_id", foreignlinkfield = "person_id")
@JoinCondition("{this}.id = {linktable}.event_id AND {linktable}.role = 'organizer'")
List<Person> organizers;
public Long getId() { return id; }
public String getTitle() { return title; }
public List<Person> getVisitors() { return visitors; }
public List<Person> getOrganizers() { return organizers; }
}
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:
// Value object (not an entity - no @Table)
public static class Address {
String street;
String city;
String zip;
public String getStreet() { return street; }
public String getCity() { return city; }
public String getZip() { return zip; }
}
@Table("customer")
public static class Customer {
@Id Long id;
String name;
@Embedded(prefix = "ship_")
Address shippingAddress;
@Embedded(prefix = "bill_")
Address billingAddress;
public Long getId() { return id; }
public String getName() { return name; }
public Address getShippingAddress() { return shippingAddress; }
public Address getBillingAddress() { return billingAddress; }
}
@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 a table-per-subclass inheritance mapping for a base class. Each subclass has its own table that shares the same primary key with the base table.
Target: Class (on the base class)
Parameters:
* value (Class<?>[], required): An array of subclass types that extend this base class.
*Example:
// Base class mapped to the 'person' table
@Table("person")
@SubClasses({Employee.class, Customer.class})
public static class Person {
@Id Long id;
String name;
public Long getId() { return id; }
public String getName() { return name; }
}
// Employee subclass - has its own 'employee' table
@Table("employee")
public static class Employee extends Person {
String department;
BigDecimal salary;
public String getDepartment() { return department; }
public BigDecimal getSalary() { return salary; }
}
// Customer subclass - has its own 'customer' table
@Table("customer")
public static class Customer extends Person {
Integer loyaltyPoints;
public Integer getLoyaltyPoints() { return 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;
}