【问题标题】:Vert.x Web , GraphQL , Hibernate ReactiveVert.x Web , GraphQL , Hibernate 反应式
【发布时间】:2022-08-09 23:57:27
【问题描述】:

我打算用 Vert.x web 和 GraphQL 写一个 Api
我已经用 Hibernate 反应式连接了数据库

    public void start(final Promise<Void> startPromise)
    {
        try
        {
            vertx.executeBlocking(e ->
            {
                try
                {
                    hibernateConfig();
                    e.complete();
                }
                catch (Exception exception)
                {
                    e.fail(exception.getCause());
                }

            }).onComplete(event ->
            {
                try
                {
                    runServer(startPromise);
                }
                catch (Exception e)
                {
                    throw new RuntimeException(e);
                }
            }).onFailure(Throwable::printStackTrace);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private void runServer(final Promise<Void> startPromise) throws Exception
    {
        final HttpServer httpServer = vertx.createHttpServer();

        final Router router = Router.router(vertx);

        router.route().handler(BodyHandler.create());

        router.post(\"/graphql\").handler(super::graphqlHandler);

        // register `/graphiql` endpoint for the GraphiQL UI
        final GraphiQLHandlerOptions graphiqlOptions = new GraphiQLHandlerOptions().setEnabled(true);
        router.route(\"/graphiql/*\").handler(GraphiQLHandler.create(graphiqlOptions));

        final URL resource = getClass().getResource(\"/static\");

        if (resource != null) router.route(\"/static/*\").handler(StaticHandler.create(resource.getFile()));
        else throw new Exception(\"Cannot set static\");

        httpServer.requestHandler(router).listen(PORT , \"localhost\" , event ->
        {
            if (event.succeeded())
            {
                System.out.printf(\"Server run on port %d!\\n\" , PORT);
                startPromise.complete();
            }
            else
            {
                System.out.println(\"Error run server!\");
                startPromise.fail(event.cause());
            }
        });
    }

    private void hibernateConfig()
    {
        Uni.createFrom().deferred(Unchecked.supplier(() ->
        {
            final Configuration configuration = new Configuration().setProperties(getHibernateProperties());

            final Set<Class<?>> entitiesClasses = getEntitiesClasses();

            if (entitiesClasses != null)
            {
                for (final Class<?> entity : entitiesClasses) configuration.addAnnotatedClass(entity);
            }
            else logger.error(\"Cannot found entities\");

            final StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder()
                    .addService(Server.class , this)
                    .applySettings(configuration.getProperties());

            final StandardServiceRegistry registry = builder.build();

            sessionFactory = configuration.buildSessionFactory(registry).unwrap(Mutiny.SessionFactory.class);

            if (!sessionFactory.isOpen()) throw new RuntimeException(\"Session is close!\");

            logger.info(\"✅ Hibernate Reactive is ready\");

            return Uni.createFrom().voidItem();
        })).convert().toCompletableFuture().join();
    }

    private Properties getHibernateProperties()
    {
        final Properties properties = new Properties();
        properties.setProperty(Environment.DRIVER , \"org.mysql.jdbc.DRIVER\");
        properties.setProperty(Environment.URL , \"jdbc:mysql://localhost:3306/DBNAME\");
        properties.setProperty(Environment.USER , \"USENAME\");
        properties.setProperty(Environment.PASS , \"PASSWORD\");
        properties.setProperty(Environment.DIALECT , \"org.hibernate.dialect.MySQL55Dialect\");
        properties.setProperty(Environment.HBM2DDL_DATABASE_ACTION , \"create\");
        properties.setProperty(Environment.SHOW_SQL , \"false\");
        properties.setProperty(Environment.POOL_SIZE , \"10\");
        return properties;
    }

到目前为止,它没有给出任何错误并创建实体

当我想做一个插入时给出错误

    public Future<UsersDto> addUserTest(final DataFetchingEnvironment environment)
    {
        return Future.future(event ->
        {
            final AddUsersDto addUsersDto = Dto.mapped(environment.getArguments() , \"user\" , AddUsersDto.class);

            final Users user = UsersMapper.toUsers(addUsersDto);

            try
            {
                vertx.executeBlocking(e ->
                        {
                            try
                            {
                                sessionFactory.withTransaction(
                                                (session , transaction) ->
                                                        session.persist(user)
                                                                .chain(session::flush)
                                        )
                                        .invoke(() -> e.complete(user))

                                        .onFailure()
                                        .invoke(e::fail)

                                        .await()
                                        .indefinitely();
                            }
                            catch (Exception exception)
                            {
                                exception.printStackTrace();
                                e.fail(exception.getCause());
                            }
                        })
                        .onComplete(e -> event.complete(UsersMapper.toUsersDto((Users) e.result())))
                        .onFailure(e -> event.fail(e.getCause()));
            }
            catch (Exception e)
            {
                e.printStackTrace();
                event.complete(UsersDto.builder().build());
            }
        });
    }

错误:

sessionFactory.withTransaction(
                (session , transaction) ->
                        session.persist(user)
                                .chain(session::flush)
        )
        .invoke(() -> e.complete(user))

        .onFailure()
        .invoke(e::fail)

        .await()
        .indefinitely(); // This line gives an error

错误文字:

java.lang.IllegalStateException: HR000068: 此方法应专门从 Vert.x EventLoop 线程调用;当前在线程 \'vert.x-worker-thread-1\' 上运行

如果有人知道问题,请帮助我

    标签: java hibernate graphql vert.x hibernate-reactive


    【解决方案1】:

    问题是您正在工作线程中运行所有内容(使用executeBlocking)。

    如果您正在编写响应式代码,则无需等待结果可用。

    代码应如下所示:

        public Future<UsersDto> addUserTest(final DataFetchingEnvironment environment) {
            return Future.future(event -> {
                final AddUsersDto addUsersDto = Dto.mapped(environment.getArguments() , "user" , AddUsersDto.class);
                final Users user = UsersMapper.toUsers(addUsersDto);
                sessionFactory
                    .withTransaction( (session , tx) -> session.persist(user) )
                    .subscribe().with( event::complete, event::fail )
            });
        }
    

    您也不需要刷新,因为有交易。

    There is a working example on the Hibernate Reactive repository

    【讨论】:

      猜你喜欢
      • 2020-09-18
      • 2020-02-12
      • 2020-08-28
      • 2020-11-07
      • 2020-03-16
      • 2020-01-10
      • 1970-01-01
      • 2021-08-31
      • 2018-04-22
      相关资源
      最近更新 更多