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 inheritance mapping |
|
Annotation |
Subclass discriminator mapping |
|
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 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;
}