com.plugback:jpa

Plugback JPA is a module that allows you to extend the Java Persistence API to query your DB using an sql-like concise and typesafe syntax.


License
Apache-2.0

Documentation

Plugback JPA - Type safe JPA queries using Xtend

Plugback JPA is a module that allows you to extend the Java Persistence API to query your DB using an sql-like concise and typesafe syntax.

What do you need

To use Plugback JPA you need to add this maven dependency:

<dependency>
    <groupId>com.plugback</groupId>
    <artifactId>jpa</artifactId>
    <version>2.0.0</version>
</dependency>

You also need:

  • the Xtend library (of course :-) )
  • to add the import import static extension com.plugback.jpa.DBX.* to your class.
  • a JPA EntityManager

Main features

Below we discuss the main features of Plugback JPA. It is assumed you have a db object of type EntityManager and that you are persisting the JPA class MyEntity:

@Entity
class MyEntity {

    @Id
    @Property Long id
    @Property String name
    @Property String email

}

Note that @Property refers to the Plugback Active @Property annotation, and not the Xtend built-in @Property. See the Important Notes section below for more details.

Plugback Active is included automatically when importing the libreary using maven.

Ok, let's start with the features:

FindAll

You can use the syntax below to retrieve all stored entities of a specified class from your db:

var myEntities = db.find(MyEntity).resultList

The findAll method is a shortcut method to get all objects of a particular class:

var myEntities = db.findAll(MyEntity)

where myEntities will be a collection having generic type MyEntity.

Where

One of the most powerful methods of Plugback JPA is the where method. Let's see an example:

db.find(MyEntity).where[email = "email@somewhere.ops"].resultList

The method above allows you to filter the entities in the DB based on a class fields, in a completely type-safe way. and or boolean operators are supported:

db.find(MyEntity).where[id = 1L or id = 2L].resultList
db.find(MyEntity).where[id = 1L and name = "romeo"].resultList

The like operator is supported too:

db.find(MyEntity).where[email like("%me%")].resultList
db.find(MyEntity).where[email like("%me%") and name like("%ro%")].resultList

Since version 2.0.0 you can use operators other than "=" into where clauses. For example take a look at the code below:

db.find(MyEntity).where[id >= 1L].resultList
db.find(MyEntity).where[id >= 1 and id < 5].resultList

And since version 2.0.0 nested object are supported too, so you can write something like this:

...where [address.street = "my street"] 

OrderBy

Plugback JPA allows you to specify how to order the results from the database:

db.find(MyEntity).where[name = "romeo"].orderBy[name].resultList
db.find(MyEntity).where[name = "romeo"].orderBy[name asc].resultList
db.find(MyEntity).where[name = "romeo"].orderBy[name desc].resultList

Immediately after using the method where you can take the results or order it using the above syntax. In addition to the class fields, you can add the asc or desc keywords to specify the sort order.

Nested objects are supported in the orderBy clause too.

Pagination

The Plugback JPA module supports pagination of results. Simply specify the page you want and its size after the resultList command:

db.find(MyEntity).where[name = "romeo"].orderBy[name].resultList[page = 1 size = 50]

When using square brackets, default values for page and size are 1 and 10 respectively, so you can specify only the page with size 10 or the size only for the first page.

Alternatively, the setPageSize method can be used immediately after the where method or after the orderBy method. setPageSize allows you to specify the page size and getPage is used to specify which page is required.

Transactions

If you were used to @Transactional annotation in Guice or something similar in Spring, forget about it. Plugback JPA gives you a clear and coincise syntax for managing transactions.

Let's take a look:

db.transaction [
            db.merge(new TestUserPojo => [id = 201L])
        ]

Everything inside square brackets will be part of the transaction.

There is the possibility to fine control what should happen in case of errors, like rolling back:

db.transaction [
            db.merge(new TestUserPojo => [id = 202L])
            throw new IllegalStateException
        ].error[rollback]

But you can add any other instruction inside the error square brackets.

You can also define some code to be executed only if the transaction was successful:

db.transaction [
            db.merge(new TestUserPojo => [id = 202L])
            throw new IllegalStateException
        ].success[println("everything is fine")].error[rollback println("ops")]

Important notes

The where method works only with POJOs, so you can not use classes in which the fields are named with the _ prefix. Unfortunately the @Data and @Property built in Xtend active annotations do not create standard POJOs, and are not supported at this time.

Alternatively you can use the @Property active annotation form the Plugback Active module.

Backed up by tests

Plugback JPA has been heavily tested to validate the functionality. There is also a test to check the performance: about 10K tests executed each query with an average of 4 ms (2 ms variance).

The tests can be run on your machine using the classes TestDBExtension and TestDBTransaction, which also show several use cases of Plugback JPA.