Interface Template


public interface Template
Template is a helper class that increases productivity when performing common NoSQL operations. The Template feature in Jakarta NoSQL simplifies the implementation of common database operations by providing a basic API to the underlying persistence engine. It follows the standard DAO (Data Access Object) pattern, a common design pattern used in software development.

The Template pattern involves creating a skeletal structure for an algorithm, with some steps implemented and others left to be implemented by subclasses. Similarly, the Template feature in Jakarta NoSQL makes a skeleton around NoSQL database operations, allowing developers to focus on implementing the specific logic required for their application.

Overall, the Template feature in Jakarta NoSQL provides a simple and efficient way to implement common database operations while following established design patterns like the Template Method. By using the Template feature, developers can save time and effort in implementing their NoSQL database operations, allowing them to focus on other aspects of their application.

@Inject
Template template;

Book book = Book.builder()
        .id(id)
        .title("Java Concurrency in Practice")
        .author("Brian Goetz")
        .year(Year.of(2006))
        .edition(1)
        .build();

template.insert(book);

Optional<Book> optional = template.find(Book.class, id);

System.out.println("The result " + optional);

template.delete(Book.class,id);

Furthermore, in CRUD (Create, Read, Update, Delete) operations, Template provides a fluent API for selecting, deleting, and querying entities, offering the ability to search and remove beyond the ID attribute. Take a look at QueryMapper for more detail about the provided fluent-API.

@Inject
Template template;

List<Book> books = template.select(Book.class)
        .where("author")
        .eq("Joshua Bloch")
        .and("edition")
        .gt(3)
        .results();

Stream<Book> books = template.select(Book.class)
        .where("author")
        .eq("Joshua Bloch")
        .stream();

Optional<Book> optional = template.select(Book.class)
        .where("title")
        .eq("Java Concurrency in Practice")
        .and("author")
        .eq("Brian Goetz")
        .and("year")
        .eq(Year.of(2006))
        .singleResult();

template.delete(Book.class)
        .where("author")
        .eq("Joshua Bloch")
        .and("edition")
        .gt(3)
        .execute();

Since:
1.0.0
See Also:
  • Method Details

    • insert

      <T> T insert(T entity)
      Inserts an entity into the database. If an entity of this type with the same unique identifier already exists in the database and the database supports ACID transactions, then this method raises an error. In databases that follow the BASE model or use an append model to write data, this exception is not thrown.

      The entity instance returned as a result of this method must include all values written to the database, including all automatically generated values and incremented values that changed due to the insert. After invoking this method, do not continue to use the instance supplied as a parameter. This method makes no guarantees about the state of the instance that is supplied as a parameter.

      @Inject
      Template template;
      
      Book book = new Book("978-0132350884", "Clean Code", "Robert C. Martin");
      Book insertedBook = template.insert(book);
      
      Type Parameters:
      T - the entity type
      Parameters:
      entity - the entity to insert. Must not be null.
      Returns:
      the inserted entity, which may or may not be a different instance depending on whether the insert caused values to be generated or automatically incremented.
      Throws:
      NullPointerException - if the entity is null.
    • insert

      <T> T insert(T entity, Duration ttl)
      Inserts an entity into the database with an expiration to the entity. If an entity of this type with the same unique identifier already exists in the database and the database supports ACID transactions, then this method raises an error. In databases that follow the BASE model or use an append model to write data, this exception is not thrown.

      The entity instance returned as a result of this method must include all values written to the database, including all automatically generated values and incremented values that changed due to the insert. After invoking this method, do not continue to use the instance supplied as a parameter. This method makes no guarantees about the state of the instance that is supplied as a parameter.

      Time-To-Live (TTL) is a feature provided by some NoSQL databases where data is automatically removed from the database after a specified duration. When inserting an entity with a TTL, the entity will be automatically deleted from the database after the specified duration has passed since its insertion. If the database does not support TTL or if the TTL feature is not enabled, this operation will not have any effect on the entity's expiration.

      
      @Inject
      Template template;
      
      SessionToken token = new SessionToken("abc123", "user-42", Instant.now());
      Duration ttl = Duration.ofMinutes(30);
      
      SessionToken inserted = template.insert(token, ttl);
      
      Type Parameters:
      T - the entity type
      Parameters:
      entity - the entity to insert. Must not be null.
      ttl - time to live
      Returns:
      the inserted entity, which may or may not be a different instance depending on whether the insert caused values to be generated or automatically incremented.
      Throws:
      NullPointerException - if the entity is null.
      UnsupportedOperationException - when the database does not provide TTL
    • insert

      <T> Iterable<T> insert(Iterable<T> entities)
      Inserts multiple entities into the database. If any entity of this type with the same unique identifier as any of the given entities already exists in the database and the database supports ACID transactions, then this method raises an error. In databases that follow the BASE model or use an append model to write data, this exception is not thrown.

      The entities within the returned Iterable must include all values written to the database, including all automatically generated values and incremented values that changed due to the insert. After invoking this method, do not continue to use the entity instances that are supplied in the parameter. This method makes no guarantees about the state of the entity instances that are supplied in the parameter. The position of entities within the Iterable return value must correspond to the position of entities in the parameter based on the unique identifier of the entity.

      Type Parameters:
      T - the entity type
      Parameters:
      entities - entities to insert.
      Returns:
      an iterable containing the inserted entities, which may or may not be different instances depending on whether the insert caused values to be generated or automatically incremented.
      Throws:
      NullPointerException - if the iterable is null or any element is null.
    • insert

      <T> Iterable<T> insert(Iterable<T> entities, Duration ttl)
      Inserts multiple entities into the database with the expiration date. If any entity of this type with the same unique identifier as any of the given entities already exists in the database and the database supports ACID transactions, then this method raises an error. In databases that follow the BASE model or use an append model to write data, this exception is not thrown.

      The entities within the returned Iterable must include all values written to the database, including all automatically generated values and incremented values that changed due to the insert. After invoking this method, do not continue to use the entity instances that are supplied in the parameter. This method makes no guarantees about the state of the entity instances that are supplied in the parameter. The position of entities within the Iterable return value must correspond to the position of entities in the parameter based on the unique identifier of the entity.

      Time-To-Live (TTL) is a feature provided by some NoSQL databases where data is automatically removed from the database after a specified duration. When inserting entities with a TTL, the entities will be automatically deleted from the database after the specified duration has passed since their insertion. If the database does not support TTL or if the TTL feature is not enabled, this operation will not have any effect on the expiration of the entities.

      @Inject
      Template template;
      
      List<SessionToken> tokens = List.of(
          SessionToken.builder()
              .id("abc123")
              .userId("user-42")
              .issuedAt(Instant.now())
              .build(),
      
          SessionToken.builder()
              .id("def456")
              .userId("user-99")
              .issuedAt(Instant.now())
              .build()
      );
      
      Iterable<SessionToken> insertedTokens = template.insert(tokens);
      
      Type Parameters:
      T - the entity type
      Parameters:
      entities - entities to insert.
      ttl - time to live
      Returns:
      an iterable containing the inserted entities, which may or may not be different instances depending on whether the insert caused values to be generated or automatically incremented.
      Throws:
      NullPointerException - if the iterable is null or any element is null.
      UnsupportedOperationException - if the database does not provide time-to-live for insert operations.
    • update

      <T> T update(T entity)
      Modifies an entity that already exists in the database.

      For an update to be made, a matching entity with the same unique identifier must be present in the database. In databases that use an append model to write data or follow the BASE model, this method behaves the same as the insert(T) method.

      If the entity is versioned (for example, with an annotation or by another convention from the entity model such as having an attribute named version), then the version must also match. The version is automatically incremented when making the update.

      Non-matching entities are ignored and do not cause an error to be raised.

      @Inject
      Template template;
      
      Book book = Book.builder()
          .isbn("978-1234567890")
          .title("Domain-Driven Design")
          .version(1)
          .build();
      
      Book updated = template.update(book);
      
      Type Parameters:
      T - the entity type
      Parameters:
      entity - the entity to update. Must not be null.
      Returns:
      the updated entity, which may or may not be a different instance depending on whether the update caused values to be generated or automatically incremented.
      Throws:
      NullPointerException - if the entity is null.
    • update

      <T> Iterable<T> update(Iterable<T> entities)
      Modifies entities that already exist in the database.

      For an update to be made to an entity, a matching entity with the same unique identifier must be present in the database. In databases that use an append model to write data or follow the BASE model, this method behaves the same as the insert(Iterable) method.

      If the entity is versioned (for example, with an annotation or by another convention from the entity model such as having an attribute named version), then the version must also match. The version is automatically incremented when making the update.

      Non-matching entities are ignored and do not cause an error to be raised.

      @Inject
      Template template;
      
      List<Book> booksToUpdate = List.of(
          Book.builder().isbn("978-1111111111").title("Effective Java").version(1).build(),
          Book.builder().isbn("978-2222222222").title("Clean Code").version(2).build()
      );
      
      Iterable<Book> updatedBooks = template.update(booksToUpdate);
      
      Type Parameters:
      T - the entity class type
      Parameters:
      entities - entities to update.
      Returns:
      the number of matching entities that were found in the database to update.
      Throws:
      NullPointerException - if either the iterable is null or any element is null.
    • delete

      <T> void delete(T entity)
      Deletes a given entity. Deletion is performed by matching the Id, and if the entity is versioned (for example, with jakarta.persistence.Version), then also the version. Other attributes of the entity do not need to match.
      @Inject
      Template template;
      
      SessionToken token = SessionToken.builder()
          .token("abc123")
          .userId("user-42")
          .version(1)
          .build();
      
      template.delete(token);
      
      Type Parameters:
      T - the entity type
      Parameters:
      entity - must not be null.
      Throws:
      NullPointerException - when the entity is null
    • delete

      <T> void delete(Iterable<? extends T> entities)
      Deletes the given entities. Deletion of each entity is performed by matching the unique identifier, and if the entity is versioned (for example, with jakarta.persistence.Version), then also the version. Other attributes of the entity do not need to match.
      @Inject
      Template template;
      
      List<SessionToken> tokens = List.of(
          SessionToken.builder()
              .token("abc123")
              .userId("user-42")
              .version(1)
              .build(),
          SessionToken.builder()
              .token("def456")
              .userId("user-99")
              .version(2)
              .build()
      );
      
      template.delete(tokens);
      
      Type Parameters:
      T - the entity type
      Parameters:
      entities - Must not be null. Must not contain null elements.
      Throws:
      NullPointerException - If the iterable is null or contains null elements.
    • find

      <T,K> Optional<T> find(Class<T> type, K id)
      Retrieves an entity by its Id.

      Example usage:

      @Inject
      Template template;
      
      Optional<SessionToken> token = template.find(SessionToken.class, "abc123");
      
      Type Parameters:
      T - the entity class type
      K - the id type
      Parameters:
      type - the entity class
      id - the id value
      Returns:
      the entity instance, otherwise Optional.empty()
      Throws:
      NullPointerException - when either the type or id are null
    • delete

      <T,K> void delete(Class<T> type, K id)
      Deletes by ID or key.
      @Inject
      Template template;
      
      template.delete(SessionToken.class, "abc123");
      
      Type Parameters:
      T - the entity class type
      K - the id type
      Parameters:
      type - the entity class
      id - the id value
      Throws:
      NullPointerException - when either the type or id are null
    • select

      <T> QueryMapper.MapperFrom select(Class<T> type)
      Start a query using the fluent API. The return value is a mutable and non-thread-safe instance.
      @Inject
      Template template;
      
      List<Person> results = template.select(Person.class)
          .where("name").eq("Ada")
          .and("age").gte(30)
          .orderBy("age").asc()
          .limit(10)
          .result();
      
      Type Parameters:
      T - the entity type
      Parameters:
      type - the entity class
      Returns:
      a QueryMapper.MapperFrom instance
      Throws:
      NullPointerException - when type is null
      UnsupportedOperationException - when the database cannot operate, such as key-value where most operations are key-based.
    • delete

      <T> QueryMapper.MapperDeleteFrom delete(Class<T> type)
      Start a query builder using the fluent API. The returned value is a mutable and non-thread-safe instance.
      @Inject
      Template template;
      
      template.delete(Book.class)
          .where("author").eq("Ada")
          .and("publishedYear").gte(2020)
          .execute();
      
      Type Parameters:
      T - the entity type
      Parameters:
      type - the entity class
      Returns:
      a QueryMapper.MapperDeleteFrom instance
      Throws:
      NullPointerException - when type is null
      UnsupportedOperationException - when the database cannot operate, such as key-value where most operations are key-based.
    • update

      <T> QueryMapper.MapperUpdateFrom update(Class<T> type)
      Start an update builder using the fluent API. The returned value is a mutable and non-thread-safe instance.
      @Inject
      Template template;
      
      template.update(Book.class)
          .set("title").to("Domain-Driven Design with Java")
          .set("publishedYear").to(2025)
          .where("author").eq("Ada")
          .execute();
      
      This operation updates matching entities based on the defined predicates. The update semantics and supported operations depend on the underlying database.
      Type Parameters:
      T - the entity type
      Parameters:
      type - the entity class
      Returns:
      a QueryMapper.MapperUpdateFrom instance
      Throws:
      NullPointerException - when type is null
      UnsupportedOperationException - when the database cannot operate, such as key-value stores that only support key-based updates.
    • query

      Query query(String query)
      Creates a query from a raw string using Jakarta Common Query Language (JCQL).

      The entity type is inferred from the query string (e.g., FROM Person), so no result class needs to be explicitly passed.

      The returned Query instance is mutable and not thread-safe.

      Example usage:

      Query query = template.query("SELECT * FROM Person WHERE name = :name");
      List<Person> people = query.bind("name", "Ada").result();
      
      Parameters:
      query - the Jakarta Common Query Language (JCQL) string to execute (e.g., SELECT * FROM Person WHERE active = true)
      Returns:
      a new Query instance bound to this query string
      Throws:
      NullPointerException - if the query string is null
      UnsupportedOperationException - if the database does not support dynamic queries
      Since:
      1.1.0
    • typedQuery

      <T> TypedQuery<T> typedQuery(String query, Class<T> type)
      Creates a TypedQuery using the given query string and result type.

      This method provides a type-safe way to execute queries by explicitly specifying the expected result type. The provided type must be one of the following:

      • An entity class annotated with @Entity. The query may explicitly include a FROM clause, or omit it if the entity can be inferred from the type parameter.
      • A Java record annotated with @Projection, which maps partial or flattened results based on the query output.

      When using a projection, the query can omit the SELECT clause entirely if the record component names match the entity’s attributes. The FROM clause can also be omitted if the Projection.from() attribute is specified.

      If the query references a different entity than the one implied by the type argument, an IllegalArgumentException may be thrown by the provider to indicate a mismatch.

      This method returns a TypedQuery, which improves safety and readability by:

      • Restricting the result type to T, eliminating the need for casting
      • Allowing fluent parameter binding and result handling
      List<TechProductView> techProducts = template
          .typedQuery("FROM Product WHERE category = 'TECH'", TechProductView.class)
          .result();
      
      Optional<PromotionalProduct> promo = template
          .typedQuery("WHERE price < :maxPrice", PromotionalProduct.class)
          .bind("maxPrice", 100)
          .singleResult();
      
      Type Parameters:
      T - the type of the result
      Parameters:
      query - the query string using Jakarta Common Query Language (JCQL)
      type - the expected result type (entity or projection class)
      Returns:
      a TypedQuery instance to bind parameters and fetch results
      Throws:
      NullPointerException - if the query or type is null
      IllegalArgumentException - if the provided type is incompatible with the entity in the query
      UnsupportedOperationException - if the query is not supported by the underlying provider
      Since:
      1.1.0