Skip to content
cjsteele edited this page Jan 7, 2015 · 3 revisions

Core API

fruit-core contains the core API (SPI) that should be used in client applications. fruit-jpa provides a basic implementation using JPA (Java Persistence API).

Identifiable

The Identifiable interface represents an entity that is managed by a respective Repository. It uses a generic parameter for the type of key by which an instance is identified. The interface provides methods to set and retrieve this key.

/**
 * Represents objects that can be uniquely identified by a key.
 * 
 * @param <K> The key type
 */
public interface Identifiable<K> extends Serializable {
    /**
     * Gets the current key.
     * 
     * @return the key
     */
    K getId();

    /**
     * Sets the key.
     * 
     * @param id the key
     */
    void setId(K id);
}

Example

In a common use case, where entities mapped to relational tables use generated long values as identity, a base entity could be defined as

class SomeEntity implements Identifiable<Long> {
    // ...
}

Repository

The org.cdlflex.fruit.Repository class is the centrepiece of the fruit API. It represents a generic DAO (Data Access Object) that manages instances of type org.cdlflex.fruit.Identifiable.

It provides basic CRUD (Create, Read, Update, Delete) functionality by the following methods

  • save (upsert/merge command, i.e. creates non-persistent and updates existing entities)
  • remove
  • get (Lookup via ID)

Additionally, it provides the following utilities:

  • create (creates a new non-persistent instance of the entity type which the Repository manages)
  • count (returns the amount of entities in the repository)
  • find (Querying using Filter)
  • getPage, findPage (Paginated querying using offset/limit clauses)

Querying

Fruit provides simple querying facilities that allow filtering, ordering and pagination

  • Filtering

    • Filter A simple representation of an SQL WHERE clause. It can consist of a single Predicate or connect several Predicate instances using a specified Connective
    • Connective Logical connective enum (AND, OR)
    • Predicate A triple (key, operator, value) that represents a logical expression (e.g. ("age", Operator.GT, 30)).
    • Operator enum representation of logical expression operators, (>, <, >=, <=, =, IN, LIKE, BETWEEN)
  • Ordering

    • OrderBy Representation of an ORDER BY clause, which connects one or more SortSpecification instances.
    • SortSpecification A tuple that binds a SortOrder to a specified key (e.g. ("age", SortOrder.ASC))
    • SortOrder enum representation of sort order (ascending ASC, descending DESC, unsorted `NONE)
  • Pagination (Repository methods that take a limit and offset value)

    • Repository#getPage
    • Repository#findPage

Examples

This mixed set of examples should give you an idea of how the querying works. Check out the API docs for more information (the Repository interface provides various combinations of filtering/pagination/ordering).

The examples use the model used in the tests for fruit-jpa which can be found here

They all assume an existing instance of Repository<Person>.

Find all Person instances ordered by their name in ascending order

repository.getAll(new OrderBy(new SortSpecification("name", SortOrder.ASC)));
// equivalent to
repository.getAll(new OrderBy("name"));

Find all Person instances ordered by their name in ascending order and age in descending order

OrderBy order = new OrderBy();
order.by(new SortSpecification("name"));
order.by(new SortSpecification("age", SortOrder.DESC));
repository.getAll(order);

Find all Person instances that are older than 30

Filter filter = new Filter();
filter.add(new Predicate("age", Operator.GT, 30));
// also works with string representations of operators, i.e. new Predicate("age", ">", 30)
// `add` also takes the arguments of `new Predicate`, i.e. filter.add("age", Operator.GT, 30);
List<Person> result = repository.find(filter)

Return the 3 oldest Person instances who's name start with 'Hubert'

Filter filter = new Filter();
filter.add("name", Operator.LIKE, "Hubert%");
        
OrderBy order = new OrderBy("age", SortOrder.DESC);
        
repository.findPage(filter, order, 3, 0);

Return the amount of entities that satisfy the given filter

Filter filter = new Filter(Connective.AND);
filter.add(new Predicate("age", Operator.GT, 30));
filter.add(new Predicate("name", Operator.LIKE, "Hubert%"));
long amountOfHubertsOverTheAgeOfThirty = repository.count(filter)

Limitations

There is no support for

  • subqueries
  • expressions using both AND and OR connectives
  • projections
  • grouping
The fruit logo

Table of Content

Clone this wiki locally