Skip to content

OpenLiberty/draft-guide-jakarta-data

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Data Persistence with Jakarta Data

What you’ll learn

You will learn how to use Jakarta Data to store data as well as the simple, yet powerful options it provides for querying data. This will include writing queries that are created from the method name, as well as queries using annotations. Finally, you will learn about the Jakarta Data Query Language (JDQL).

The application demonstrates a number of different queries that are possible with Jakarta Data. Once you have completed the guide you can try writing your own queries with the provided sample data.

What is Jakarta Data?

Jakarta Data is a new data access specification being released with Jakarta EE 11. It provides a new API for simplified data access. Jakarta Data follows the Repository design pattern for data access, and allows for implementations which may support both SQL and NoSQL data stores. It also provides enhanced type safety with a Static Metamodel.

This application allows you to run queries against a set of shipping packages which have a variety of dimensions and destinations. Go to the http://localhost:9080 URL to see all the application data. You will see a column of queries, some of which will accept input. To start find the findAll query with no inputs. Selecting this will return all of the query data similar to the following:

ID  Length  Width   Height  Destination
1   10      20      10      Rochester
2   30      10      10      Austin
3   5       10      5       RTP
4   24      15      6       Rochester
5   15      7       2       Austin
6   8       5       3       Rochester
7   16      3       15      RTP
8   2       15      18      Rochester

You can then try some of the queries which use input to see how it changes which packages are returned. If you find the query named findByLengthGreaterThan and enter 25 in the box labeled length, you can then run the query by clicking the ➜ button. The result should look like the following, with only lengths greater than 25:

ID  Length  Width  Height  Destination
2   30      10	   10      Austin
16  38      16     25      Markham

Creating an entity and repository

Navigate to the start directory to begin.

In Jakarta Data an entity defines the structure for persisting a piece of data. This structure is represented by a Java object and its associated fields. The entity you will work with in this guide is a record class called Package.java, which contains a few fields.

Package.java

link:finish/src/main/java/io/openliberty/guides/data/Package.java[role=include]

Packages.java

link:finish/src/main/java/io/openliberty/guides/data/Packages.java[role=include]

A common pattern with repositories is to use the plural of the entity, so the repository you will be working with in this guide is called Packages.java. Repositories in Jakarta Data provide a simplified means for interacting with persistent data. They are annotated with the @Repository annotation. Jakarta Data provides several built-in repositories with common methods which can be extended with application-specific queries. The CrudRepository interface provides methods for Create, Read, Update, and Delete (CRUD) operations.

CrudRepository provides two options for persisting entities, insert and save. The first option insert will persist an entity only if the entity does not already exist. The save option will persist an entity even if it already exists, allowing it to be used for updating entities as well. CrudRepository provides a delete method for removing entities.

Package p1 = new Package(1, 10f, 20f, 10f, "Rochester");
packages.insert(p1);
packages.save(p1);
packages.delete(p1);

Query by Method Name

Query by Method Name allows you to write queries using a descriptive method name following a few intuitive rules on how the method name is structured.

Packages.java

link:finish/src/main/java/io/openliberty/guides/data/Packages.java[role=include]
Update the Packages.java class.
src/main/java/io/openliberty/guides/data/Packages.java

This allows methods like findByLengthGreaterThan(float length) or findByHeightBetween(float minHeight, float maxHeight) to automatically be turned into queries. Method names must start with an action like find, delete, or count and can include operators (such as And, Or, and Not) and conditions (such as GreaterThan, LessThan, and Between).

For more information on all of the options available with Query by Method Name, see the Query by Method Name Extension of the Jakarta Data specification.

Querying with method annotations

Queries can also be written using method annotations. This allows for additional flexibility in the queries as well as the method names.

Packages.java

link:finish/src/main/java/io/openliberty/guides/data/Packages.java[role=include]
Update the Packages.java class.
src/main/java/io/openliberty/guides/data/Packages.java

The @Find and @By annotations

The @Find annotation indicates that a method is a query which may return entities. Used in isolation it will return all entities, but by using the @By annotation, it can be limited to entities which match the value provided at runtime. The getPackagesArrivingIn method demonstrates using the @Find and @By annotations to return all packages that are destined for a specific location.

Renaming provided methods

If a method name provided by a built in Jakarta Data repository class doesn’t align with your repository you can use annotations to provide your own method. For example, using the @Insert annotation you can create a method named add instead of the insert method inherited from CrudRepository.

This method is functionally equivalent to the insert method provided by CrudRepository.

The @OrderBy annotation

To provide ordering annotatively, you can use the @OrderBy annotation. The default ordering direction is ascending. The sortedByHeightAscending method demonstrates how to obtain all of the packages in the repository sorted by the height parameter.

@OrderBy can also return in descending order by specifying descending = true in the annotation:

@OrderBy(value = "height", descending = true)

Sorting, limiting, and paging results

Jakarta Data provides the Sort and Limit classes to create queries which can be modified at runtime. It also includes a mechanism for pagination to better handle large sets of results.

Packages.java

link:finish/src/main/java/io/openliberty/guides/data/Packages.java[role=include]
Update the Packages.java class.
src/main/java/io/openliberty/guides/data/Packages.java

Sort

In addition to the @OrderBy annotation it is possible to provide sorting at runtime. This is accomplished by adding a Sort parameter to your query method like in the sorted method.

A Sort can be created and provided at runtime using the Sort class’s static methods:

Sort sort = Sort.desc("height");

Limit

Jakarta Data queries can restrict the number of entities returned at runtime by providing a Limit object to the query as shown in the shortestWithLimit method.

This method will return the shortest packages in order from shortest to longest, but limited to only the specified number of results.

Limits can be created and supplied using the Limit class’s static methods:

Limit limitTen = Limit.of(10);

Limits can also be used to access a range of entities, such as starting at the 10th entity and ending at the 20th:

Limit range = Limit.range(10,20);

Paging

When querying large amounts of data, paging is possible by adding a PageRequest parameter to your query method like in the all method. This method will return all of the packages, but with the results paginated based on the provided PageRequest.

A PageRequest can be constructed with the PageRequest class’s static methods. To request the first Page with a page size of 20 results:

Page<Package> page = packages.all(PageRequest.ofSize(20));
List<Package> results = page.content();

Navigating pages can be done from the Page object:

Page<Package> anotherPage = packages.all(page.nextPageRequest());

The Query Annotation

The @Query annotation allows users to write queries using the Jakarta Data Query Language (JDQL). Complex queries can be written concisely using JDQL. JDQL is a strict subset of the Jakarta Persistence Query Language (JPQL).

Packages.java

link:finish/src/main/java/io/openliberty/guides/data/Packages.java[role=include]
Update the Packages.java class.
src/main/java/io/openliberty/guides/data/Packages.java

For an example of a complex query simplified using JDQL, take a look at withAnyDimensionLargerThan.

This query checks for packages where the length, height, or width are larger than a threshold, which is provided as a parameter in the function. The threshold parameter is referenced in the query using :threshold. Achieving the same query with Query by Method Name would result in a very long method name and additional parameters.

JDQL supports both named and positional parameters, as well as a number of operators. This is shown in the withTotalDimensionOver query, which sums the length, width, and height of each package to check if the total exceeds a provided threshold. Unlike the named parameter syntax (:threshold) used in the previous example, this query uses positional parameter syntax with ?1 to reference the first method parameter.

See the Jakarta Data specification for a more comprehensive overview of the Jakarta Data Query Language.

Running the application

Because you are running the application in dev mode, any changes you make to the code are automatically picked up. You’re now ready to test out your queries in the browser.

Point your browser to the http://localhost:9080 URL to access the application. You can select different queries from the list and provide input parameters to see how Jakarta Data retrieves the package data.

Try experimenting with different query parameters to see how the results change. For example, use the findByLengthGreaterThan query with different length values to filter packages by length.

Where to next?

Experiment by creating your own queries. Use the existing ones in the Packages class as a starting point and then test them out in the sample application. For example, you could add a query to find packages arriving at a specific destination, which is ordered by width:

    @Find
    @OrderBy("width")
    List<Package> byWidthArrivingIn(@By("destination") String destination);

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 15