Vertx - 是否可以将RxJava和Hibernate结合起来

时间:2016-01-12 14:15:31

标签: hibernate jdbc rx-java reactive-programming vert.x

我想知道是否可以使用它:

https://github.com/vert-x3/vertx-rx

https://github.com/vert-x3/vertx-jdbc-client

并为命名查询/ DAO访问添加Hibernate。

如何使Hibernate非阻塞I / O?

1 个答案:

答案 0 :(得分:1)

最近我遇到了完全相同的问题并编写了该库: https://github.com/eraga/rxjpa2

以下是如何将其与vertx一起使用的示例。

假设您在使用JPA2 Hibernate访问的数据库中存储了User个实体。然后你会UsersDAOServiceImpl那样:

package jpa.rxjava.vertx.sample

import io.vertx.core.AsyncResult
import io.vertx.core.Handler
import io.vertx.reactivex.CompletableHelper
import io.vertx.reactivex.SingleHelper
import data.User // That's your data class
import net.eraga.rxjpa2.*
import javax.persistence.EntityManager
import javax.persistence.EntityManagerFactory

class UsersDAOServiceImpl(
        emf: EntityManagerFactory,
        readyHandler: Handler<AsyncResult<UsersDAOService>>
) : UsersDAOService {

    private lateinit var entityManager: EntityManager

    init {
        emf.rxCreateEntityManager()
                .map {
                    entityManager = it
                    this
                }
                .subscribe(SingleHelper.toObserver(readyHandler))

    }


    override fun fetchByLogin(login: String, resultHandler: Handler<AsyncResult<User>>) {
        entityManager.createQuery("SELECT i From User i where login = :login", User::class.java)
                .setParameter("login", login)
                .rxSingleResult<User>()
                .subscribe(SingleServiceHelper.toObserver(resultHandler))
    }

    override fun fetchAll(resultHandler: Handler<AsyncResult<List<User>>>) {
        entityManager.createQuery("SELECT i From User i order by modified desc", User::class.java)
                .rxResultList()
                .subscribe(SingleServiceHelper.toObserver(resultHandler))
    }

    override fun fetchById(id: Int, resultHandler: Handler<AsyncResult<User>>) {
        entityManager.rxFind(User::class.java, id)
                .subscribe(SingleServiceHelper.toObserver(resultHandler))
    }

    override fun create(user: User, resultHandler: Handler<AsyncResult<Void>>) {
        entityManager
                .rxPersist(user)
                .subscribe(CompletableHelper.toObserver(resultHandler))
    }

    override fun save(user: User, resultHandler: Handler<AsyncResult<Void>>) {
        entityManager
                .rxMerge(user)
                .toCompletable()
                .subscribe(CompletableHelper.toObserver(resultHandler))
    }

    override fun delete(id: Int, resultHandler: Handler<AsyncResult<Void>>) {
        val user = User().apply { this.id = id }
        entityManager
                .rxRemove(user)
                .subscribe(CompletableHelper.toObserver(resultHandler))
    }
}

注意SingleServiceHelper有助于将Single翻译为SingleObserver的课程:

package jpa.rxjava.vertx.sample

import com.fasterxml.jackson.core.type.TypeReference
import io.reactivex.Single
import io.reactivex.SingleObserver
import io.reactivex.SingleTransformer
import io.reactivex.annotations.NonNull
import io.reactivex.disposables.Disposable
import io.vertx.core.AsyncResult
import io.vertx.core.Future
import io.vertx.core.Handler
import io.vertx.core.buffer.Buffer
import io.vertx.reactivex.core.json.SingleUnmarshaller
import io.vertx.serviceproxy.ServiceException
import java.util.concurrent.atomic.AtomicBoolean
import java.util.function.Function


object SingleServiceHelper {
    /**
     * Adapts an Vert.x `Handler<AsyncResult<T>>` to an RxJava2 [SingleObserver].
     *
     *
     * The returned observer can be subscribed to an [Single.subscribe].
     *
     * @param handler the handler to adapt
     * @return the observer
     */
    fun <T> toObserver(handler: Handler<AsyncResult<T>>): SingleObserver<T> {
        val completed = AtomicBoolean()
        return object : SingleObserver<T> {
            override fun onSubscribe(@NonNull d: Disposable) {}
            override fun onSuccess(@NonNull item: T) {
                if (completed.compareAndSet(false, true)) {
                    handler.handle(Future.succeededFuture(item))
                }
            }

            override fun onError(error: Throwable) {
                if (completed.compareAndSet(false, true)) {
                    val ex = ServiceException(-1,error.message).apply {
                        initCause(error)
                    }
                    handler.handle(Future.failedFuture(ex))
                }
            }
        }
    }

    fun <T> unmarshaller(mappedType: Class<T>): SingleTransformer<Buffer, T> {
        return SingleUnmarshaller(Function.identity(), mappedType)
    }

    fun <T> unmarshaller(mappedTypeRef: TypeReference<T>): SingleTransformer<Buffer, T> {
        return SingleUnmarshaller(Function.identity(), mappedTypeRef)
    }
}

当您启动App Verticle时使用EntityManagerFactory实例化RxPersistence的方法:

package jpa.rxjava.vertx.sample

import io.reactivex.plugins.RxJavaPlugins
import io.vertx.core.DeploymentOptions
import io.vertx.core.Future
import io.vertx.core.VertxOptions
import io.vertx.core.json.JsonObject
import io.vertx.reactivex.core.AbstractVerticle
import io.vertx.reactivex.core.RxHelper
import io.vertx.reactivex.core.Vertx
import net.eraga.rxjpa2.RxPersistence
import org.slf4j.LoggerFactory
import javax.persistence.EntityManagerFactory

class App : AbstractVerticle() {
    private val log = LoggerFactory.getLogger(this.javaClass)

    @Throws(Exception::class)
    override fun start(startFuture: Future<Void>) {

        RxPersistence
                .createEntityManagerFactory("initiatives")
                .flatMap {
                    log.info("Done createEntityManagerFactory {}", it)
                    App.entityManagerFactory = it
                    vertx.rxDeployVerticle(UsersVerticle::class.java.name)
                }.flatMap {
                    log.info("Started {}", it)

                    vertx.rxDeployVerticle(HttpServerVerticle::class.java.name,
                            DeploymentOptions().setInstances(2))
                }.subscribe(
                        {
                            log.info("Started {}", it)
                            startFuture.complete()
                        },
                        {
                            log.error("Fail {}", it.message)
                            startFuture.fail(it)
                        }
                )
    }

    companion object {
        lateinit var entityManagerFactory: EntityManagerFactory

        @JvmStatic
        fun main(args: Array<String>) {
            System.setProperty("org.jboss.logging.provider", "slf4j")
            System.setProperty("hazelcast.logging.type", "slf4j")


            Vertx.clusteredVertx(VertxOptions().setClustered(true)) { cluster ->
                if (cluster.succeeded()) {
                    val vertx = cluster.result()

                    RxJavaPlugins.setComputationSchedulerHandler({ s -> RxHelper.scheduler(vertx) })
                    RxJavaPlugins.setIoSchedulerHandler({ s -> RxHelper.blockingScheduler(vertx) })
                    RxJavaPlugins.setNewThreadSchedulerHandler({ s -> RxHelper.scheduler(vertx) })
                    RxJavaPlugins.lockdown()

                    vertx.deployVerticle(App::class.java.name, DeploymentOptions().setConfig(JsonObject().put("local", true)))
                }
            }
        }
    }
}