Skip to content

eraga/async-jpa

Repository files navigation

Asynchronous JPA 2 with RxJava2 and Kotlin

Travis CI GitHub license GitHub stars GitHub top language

Library provides RxJava2 wrappers for blocking JPA 2 operations written with Kotlin extension functions. Though it is pretty small in size it brings agility of kotlin and RxJava to the full power of JPA.

Hibernate 5.2.5.Final and EclipseLink 2.6.5, but should work with any other JPA 2 provider. Refer to tested providers for more information.

How to use

Library setup

Add custom maven repository

repositories {
    maven {
        url 'http://nexus.eraga.net/content/repositories/public-releases/'
    }
}

Add gradle dependency to your project:

// For JPA 2.2
compile "net.eraga.jpa.async:jpa2.2-rxjava2:1.2"

// For JPA 2.1
compile "net.eraga.jpa.async:jpa2.1-rxjava2:1.2"

// For JPA 2.0 (Required for those providers that are not compatible with JPA 2.1)
compile "net.eraga.jpa.async:jpa2.0-rxjava2:1.2"
Note
Latest version is 1.2

Usage

I assume you already had set up persistence.xml file and know the basics of JPA.

Purely synthetic example how to retrieve and print a single Book title from database from cold start to release of connection:

lateinit var entityManager: EntityManager
lateinit var entityManagerFactory: EntityManagerFactory

RxPersistence
        .createEntityManagerFactory("rxJpa2-test")
        .flatMap {
            entityManagerFactory = it
            it.rxCreateEntityManager()
        }.flatMap {
            entityManager = it
            it.rxFind(Book::class.java, 1)
        }.subscribe { book ->
            println(book.title)
            entityManager.close()
            entityManagerFactory.close()
        }

Details

Persistence static class was extended via RxPersistence kotlin object. It has exactly the same methods as Persistence except they are reactive.

RxPersistence
        .createEntityManagerFactory("accountancy")
        .observeOn(Schedulers.computation())
        .map({
            emf.createEntityManager()
        })
        .subscribe {
            // do something with entityManager instance
        }

On the other hand all blocking calls of EntityManagerFactory, EntityManager, Query and TypedQuery interfaces have got extension functions.

For example TypedQuery.resultList can be accessed in reactive way like that:

val entityManager: EntityManager = ... // instantiated somewhere else

entityManager
        .createQuery("SELECT i From Employee i order by modified desc", Employee::class.java)
        .rxResultList()
        .subscribe {
        // do something with List result
        }

Persisting objects inside a single transaction have become much easier

entityManager
        .rxTransaction {
            it.persist(Book("Transaction book 1"))
            it.persist(Book("Transaction book 2"))
            it.persist(Book("Transaction book 3"))
            it.persist(Book("Transaction book 4"))
        }
        .subscribe {
            // do something on completion
        }

Single persist operation is done inside a transaction

val book = Book("rxPersistBook")
entityManager
        .rxPersist(book)
        .subscribe {
            // do something on completion
        }

Using Schedulers

Each extension can accept a Scheduler instance as an argument

// Custom Scheduler
entityManager
        .createQuery("SELECT i From Employee i order by modified desc", Employee::class.java)
        .rxResultList(Schedulers.computation())
        .subscribe {
            // do something with List result
        }

Using with Vertx

Here is a brief example of using rxjava jpa2 helper library with Vertx DAO: https://stackoverflow.com/a/50244292/1824898

That was an initial goal of writing this library :)

Tested providers

All providers should be supported. Following providers had been tested with unit tests.

Table 1. List of tested providers
API Level JPA Provider Provider version DB Engine

JPA 2.0

Hibernate

4.2.2.Final

H2

JPA 2.0

EclipseLink

2.4.2

H2

JPA 2.1

Hibernate

5.2.5.Final

H2

JPA 2.1

EclipseLink

2.6.5

H2

JPA 2.1

Kundera

3.12

neo4j

JPA 2.1

Kundera

3.12

HBase

JPA 2.1

Kundera

3.12

RDBMS

Warning
Kundera-RDBMS seems to be buggy, as it doesn’t pass certain tests while exactly same package of Hibernate (which it uses as a backend) passes all the tests.

Known issues