Represents a row in a table or query result, encapsulating the data and state of a domain entity.
An Entity instance maintains both current and original values for all attributes, tracks modifications,
and provides type-safe access to column values and foreign key relationships.
Mutable entities are NOT thread-safe. They should not be shared between threads without
external synchronization. Concurrent modifications may result in data corruption or inconsistent state.
Immutable entities ARE thread-safe. Created via immutable(), they can be safely
shared between threads. All referenced entities are also made immutable to ensure complete thread safety.
Recommended patterns for concurrent use:
Use immutable() to create thread-safe snapshots for sharing
Implement external synchronization when sharing mutable entities
Consider using immutable entities for read-only operations across threads
Create defensive copies with copy() when passing entities between threads
// Creating and working with entities
Entity customer = entities.entity(Customer.TYPE)
.with(Customer.ID, 42)
.with(Customer.NAME, "John Doe")
.with(Customer.EMAIL, "john@example.com")
.build();
// Accessing values
String name = customer.get(Customer.NAME);
Optional<String> email = customer.optional(Customer.EMAIL);
// Modifying values (if mutable)
customer.set(Customer.EMAIL, "newemail@example.com");
boolean isModified = customer.modified(Customer.EMAIL); // true
// Reverting changes
customer.revert(Customer.EMAIL); // back to "john@example.com"
// Working with foreign keys
Entity invoice = connection.selectSingle(Invoice.ID.equalTo(123));
// Access the referenced entity (automatically loaded if configured)
Entity customer = invoice.get(Invoice.CUSTOMER_FK);
// Access foreign key attributes directly
String customerName = invoice.get(Invoice.CUSTOMER_FK).get(Customer.NAME);
// Get the foreign key value
Key customerKey = invoice.key(Invoice.CUSTOMER_FK);
Returns true if one or more writable attributes have been modified from their initial value,
non-insertable and non-updatable attributes are excluded unless they are transient and modify the entity.
Returns true if the value associated with the given attribute has been modified since first set,
note that this does not apply to attributes based on derived values.
Reverts the value associated with the given attribute to its original value.
If the value has not been modified then calling this method has no effect.
Parameters:
attribute - the attribute for which to revert the value
Reverts all value modifications that have been made.
This entity will be unmodified after a call to this method.
If no modifications have been made then calling this method has no effect.
Saves the value associated with the given attribute, that is, removes the original value.
If the value has not been modified calling this method has no effect.
Parameters:
attribute - the attribute for which to save the value
Saves all the value modifications that have been made, that is, removes all original values.
This entity will be unmodified after a call to this method.
Removes the given value from this Entity along with the original value if any.
If no value is mapped to the given attribute, this method has no effect.
Returns true if a null value is mapped to the given attribute or if no mapping is found.
In case of foreign keys the value of the underlying reference column(s) is checked.
If the key is a single column key, true is returned if the associated value is null,
but in case of composite keys then true is returned if one or more non-nullable key columns
are associated with a null value.
Parameters:
attribute - the attribute
Returns:
true if the value mapped to the given attribute is null or no value is mapped
Returns the Entity instance referenced by the given ForeignKey.
If the underlying reference contains a value, that is,
a foreign key value exists but the actual referenced entity has not
been loaded, an "empty" entity is returned, containing only the referenced
key value(s). Null is returned only if the actual foreign key is null.
// Assuming Invoice has a foreign key to Customer
Entity invoice = connection.selectSingle(Invoice.ID.equalTo(42));
// Get the customer entity - may be fully loaded or just contain the key
Entity customer = invoice.entity(Invoice.CUSTOMER_FK);
if (customer != null) {
// This is always available - the foreign key value
Integer customerId = customer.get(Customer.ID);
// This may return null if customer wasn't loaded
// and the foreign key entity doesn't contain Customer.NAME
String customerName = customer.get(Customer.NAME);
}
Parameters:
foreignKey - the foreign key for which to retrieve the referenced entity
Returns true if the value associated with the given attribute has been modified since first set,
note that this does not apply to attributes based on derived values.
true if the value associated with the given attribute has been modified
modified
booleanmodified()
Returns true if one or more writable attributes have been modified from their initial value,
non-insertable and non-updatable attributes are excluded unless they are transient and modify the entity.
Returns:
true if one or more writable attributes have been modified since they were first set
Compares the values of all attributes in the given entity to the values in this entity instance.
Returns true if all attribute values available in this entity are available and equal in the comparison entity
Entity customer1 = entities.entity(Customer.TYPE)
.with(Customer.ID, 42)
.with(Customer.NAME, "John Doe")
.with(Customer.EMAIL, "john@example.com")
.build();
Entity customer2 = entities.entity(Customer.TYPE)
.with(Customer.ID, 42)
.with(Customer.NAME, "John Doe")
.with(Customer.EMAIL, "john@example.com")
.with(Customer.PHONE, "555-1234") // Extra attribute
.build();
customer1.equalValues(customer2); // true - all values in customer1 exist and are equal in customer2
customer2.equalValues(customer1); // false - customer2 has PHONE which customer1 doesn't have
Parameters:
entity - the entity to compare to
Returns:
true if all values in this entity instance are present and equal to the values in the given entity
Compares the values of the given attributes in the given entity to the values in this entity instance.
Returns true if these two entities contain values for the given attributes and all the values are equal.
Entity customer1 = entities.entity(Customer.TYPE)
.with(Customer.ID, 42)
.with(Customer.NAME, "John Doe")
.with(Customer.EMAIL, "john@example.com")
.build();
Entity customer2 = entities.entity(Customer.TYPE)
.with(Customer.ID, 42)
.with(Customer.NAME, "John Doe")
.with(Customer.EMAIL, "different@example.com")
.build();
// Compare only specific attributes
Set<Attribute<?>> nameAttributes = Set.of(Customer.ID, Customer.NAME);
customer1.equalValues(customer2, nameAttributes); // true - ID and NAME are equal
Set<Attribute<?>> allAttributes = Set.of(Customer.ID, Customer.NAME, Customer.EMAIL);
customer1.equalValues(customer2, allAttributes); // false - EMAIL differs
Parameters:
entity - the entity to compare to
attributes - the attributes to compare
Returns:
true if all the given values in this entity instance are present and equal to the values in the given entity
After a call to this method this Entity contains the same values and original values as the source entity.
A null argument to this method clears this entity instance of all values and original values.
Parameters:
entity - the entity to copy or null for clearing all values in this instance
Returns:
the affected attributes and their previous values, that is, attributes which values changed
Returns an immutable version of this entity, all foreign key entities are also immutable.
Note that this may be the same instance in case this instance is already immutable.
Thread Safety: The returned immutable entity is thread-safe and can be safely
shared between threads without external synchronization. All referenced entities
are also made immutable to ensure complete thread safety throughout the object graph.
This method is particularly useful for:
Creating thread-safe snapshots for sharing between threads
Ensuring data integrity in concurrent read operations
Caching entities safely in multi-threaded environments
Returns:
an immutable, thread-safe version of this entity
mutable
booleanmutable()
Returns whether this entity instance is mutable (can be modified).
Thread Safety: Mutable entities (returning true) are NOT thread-safe
and should not be shared between threads without external synchronization.
Immutable entities (returning false) are thread-safe and can be safely
shared between threads.
Returns:
true if this is a mutable instance, false if immutable
If the entity has no defined primary key, this method returns a pseudo primary key
containing all column values, and Entity.Key.primary() returns false.
This enables working with entities based on views or legacy tables that lack proper primary keys.
Pseudo Primary Key Behavior:
Update/Delete: Operations work correctly when the pseudo key uniquely identifies a single row
Identical Rows: If multiple rows have identical column values, delete by key throws
DeleteException since the pseudo key cannot distinguish between them
Workaround: Use condition-based delete instead of key-based delete
for tables with potentially identical rows
Typical Use Cases:
Read-only entities based on denormalized views (most common)
Legacy tables without proper primary keys (rare)
Temporary or staging tables where unique constraints aren't enforced
Returns:
the primary key of this entity, or a pseudo primary key if no primary key is defined
Returns the primary key of this entity, in its original state.
If the entity has no defined primary key, this method returns a pseudo primary key
containing all original column values, and Entity.Key.primary() returns false.
Returns:
the primary key of this entity in its original state, or a pseudo primary key if no primary key is defined