Micronaut Data

repository·5.2.x·Indexed 19 days ago

https://github.com/micronaut-projects/micronaut-data

A database access toolkit that uses Ahead-of-Time (AoT) compilation to pre-compute queries for repository interfaces, providing a high-performance, type-safe alternative to reflection-based frameworks. It supports JPA, JDBC, and Azure Cosmos DB, offering features such as compile-time generated repositories, projection queries, attribute converters, and optimistic locking.

Tokens
68.2K
Snippets
208
Records
324
Agent score
67%

What's inside Micronaut Data

  1. What is Micronaut Data

    5.2.x

    Micronaut Data is a database access toolkit that uses Ahead of Time (AoT) compilation to pre-compute queries for repository interfaces. These queries are then executed by a thin, lightweight runtime layer.

    Key advantages over traditional frameworks like Spring Data or GORM include:

    • No runtime model: Does not maintain a runtime metamodel using reflection, reducing memory consumption.
    • No query translation at runtime: Queries are translated from method definitions into actual queries by the Micronaut compiler at compilation time, rather than using regex or pattern matching at runtime.
    • No Reflection or Runtime Proxies: Improves performance and reduces memory usage by avoiding reflection caches and runtime proxies (though the underlying driver, like Hibernate, may still use reflection).
    • Type Safety: The compiler actively checks that repository methods can be implemented, failing the build if a method cannot be translated into a valid query.
  2. Capabilities of Micronaut Data MongoDB

    5.2.x

    Micronaut Data MongoDB provides a high-level data access layer for MongoDB, offering features similar to JPA and JDBC/R2DBC implementations. It uses Micronaut Serialization and BSON support to handle the interaction between the object layer and the MongoDB driver's serialization/deserialization processes.

    Key supported features include:

    • Repositories with compile-time generated filtering, aggregation, and projection queries.
    • Entity relations and cascading.
    • Transactions.
    • Joining relations.
    • JPA Criteria API support.
    • Attribute converters.
    • Optimistic locking.
  3. Supported features in Micronaut Data Azure Cosmos

    5.2.x

    Micronaut Data Azure Cosmos provides a subset of JPA-like features optimized for Azure Cosmos DB. Supported features include:

    • Compile-time generated repositories: Repositories are generated at compile time for performance.
    • Projection queries: Ability to query specific subsets of data.
    • Attribute converters: Custom logic for converting between entity attributes and database values.
    • Optimistic locking: Support for managing concurrent updates.

    Important Limitations: Unlike other Micronaut Data modules, Azure Cosmos DB does not support cascading or joins.

  4. Reactive querying with JPA

    5.2.x

    When using reactive return types with JPA, be aware that each operation runs with its own transaction and session. This can lead to issues with detached objects.

    Best Practices:

    • Take care to fetch the correct data to avoid working with detached objects.
    • For complex operations, it may be more efficient to write custom code that utilizes a single session rather than relying on multiple reactive repository calls.
  5. Configure transaction phases for @TransactionalEventListener

    5.2.x

    The @TransactionalEventListener annotation accepts a phase value that allows you to bind the listener to specific stages of a transaction lifecycle. By default, listeners trigger after a commit.

    You can customize this behavior by setting the phase attribute to one of the following transaction phases (referencing standard transaction lifecycle phases):

    • AFTER_COMMIT (Default)
    • AFTER_ROLLBACK
    • AFTER_COMPLETION
    • BEFORE_COMMIT
  6. Materialize associations in native queries using @Join

    5.2.x

    When performing explicit SQL joins in a native query, Micronaut Data does not automatically map the joined data to associated entities. To materialize these associations, use the @Join annotation.

    Key Rules:

    1. Logical Name: The value attribute of @Join must use the logical name of the field as defined in your @Entity class, not the name used in the SQL string.
    2. Alias Mapping: Use the alias attribute to specify which SQL alias corresponds to the association.
    3. Default Alias Behavior: If you do not specify an alias in the @Join annotation, Micronaut Data defaults to using the value (the field name) followed by an underscore (e.g., if the field is reviews, the default alias is reviews_).
    // Example: Many-to-One
    @Query("SELECT p.*, m_.id AS m_id, m_.name AS m_name FROM product p INNER JOIN manufacturer m_ ON p.manufacturer_id = m_.id")
    @Join(value = "manufacturer", alias = "m_")
    Product findWithManufacturer();
    
    // Example: One-to-Many (using default alias)
    @Query("SELECT b.*, r_.id AS reviews_id FROM book b LEFT JOIN review r_ ON b.id = r_.book_id")
    @Join(value = "reviews")
    Book findWithReviews();
  7. Choose a specification executor variation for async or reactive repositories

    5.2.x

    Micronaut Data provides several variations of the JpaSpecificationExecutor interface to support different programming models (async, reactive, or coroutines). When building repositories that need to execute specifications (querying, deleting, or updating data) using non-blocking patterns, select the interface that matches your preferred stack:

    • Standard: JpaSpecificationExecutor for default synchronous operations.
    • Async: AsyncJpaSpecificationExecutor for asynchronous operations.
    • Reactive Streams: ReactiveStreamsJpaSpecificationExecutor for Publisher<> based reactive streams.
    • Project Reactor: ReactorJpaSpecificationExecutor for Reactor-based (Mono/Flux) reactive programming.
    • Kotlin Coroutines: CoroutineJpaSpecificationExecutor for Kotlin-native coroutine support.
    |===| Interface | Description
    |api:data.repository.jpa.JpaSpecificationExecutor[] | The default interface for querying, deleting and updating data
    |api:data.repository.jpa.async.AsyncJpaSpecificationExecutor[] | The async version of the specifications repository
    |api:data.repository.jpa.reactive.ReactiveStreamsJpaSpecificationExecutor[] | The reactive streams - `Publisher<>` version of the specifications repository
    |api:data.repository.jpa.reactive.ReactorJpaSpecificationExecutor[] | The Reactor version of the specifications repository
    |api:data.repository.jpa.kotlin.CoroutineJpaSpecificationExecutor[] | The Kotlin version of the interface that is using coroutines
    |===|
  8. Update specific properties using CriteriaUpdate

    5.2.x

    Within an UpdateSpecification, you can use the jakarta.persistence.criteria.CriteriaUpdate object to define which fields should be updated and what their new values should be. This is typically done using the .set(field, value) method on the CriteriaUpdate instance provided in the toPredicate method.

    // Conceptual implementation of setting a property
    public class UpdateNameSpecification implements UpdateSpecification<Person> {
        private final String newName;
    
        public UpdateNameSpecification(String newName) {
            this.newName = newName;
        }
    
        @Override
        public Predicate toPredicate(Root<Person> root, CriteriaUpdate<?> query, CriteriaBuilder cb) {
            query.set("name", newName);
            return cb.equal(root.get("status"), "ACTIVE");
        }
    }