1

我构建了一个小的 Rest API 来了解更多关于 Quarkus 框架的信息。现在我想开始使用带有反应式 API 的框架,但我很难理解一些概念。目前,该项目正在使用 RESTEasy Reactive with Jackson,Hibernate Reactive with Panache 和 Postgresql Reactive Client。

这是我的课

@Table(name = "cat_role")
@Entity
public class Role extends PanacheEntityBase {
    private static final long serialVersionUID = -2246110460374253942L;

    @Id
    @Column(name = "id", nullable = false, updatable = false)
    @GeneratedValue
    public UUID id;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "name", nullable = false, length = 18)
    public UserRole name;

    public enum UserRole {
        Administrador, Asesor_Empresarial, Asesor_Academico, Alumno
    }
    
}

现在,在我的服务中(势在必行),我执行以下操作:

角色类

    public static Boolean existsRoleSeed(){
        return Role.count() > 0;
    }

角色服务类

    @Transactional
    public void seedRoles() {
        if (!Role.existsRoleSeed()) {
            for(Role.UserRole userRole: Role.UserRole.values()){
                Role role = Role.builder()
                        .name(userRole)
                        .build();
                
                role.persist();
            }
        }
    }

这显然会在数据库中注册 UserRole 枚举中的所有角色,并且它工作正常。我想要实现的是复制这种方法,但使用反应形式。这些是我在代码中所做的更改

角色类

    public static Uni<Boolean> existsRoleSeed() {
        return Role.count().map(x -> x > 0);
    }

角色服务类

    @ReactiveTransactional
    public void seedRoles() {
        Role.existsRoleSeed()
                .map(exists -> {
                    if (!exists) {
                        Multi.createFrom()
                                .iterable(Arrays
                                        .stream(Role.UserRole.values())
                                        .map(userRole -> Role.builder()
                                                .name(userRole)
                                                .build())
                                        .collect(Collectors.toList()))
                                .map(role -> role.persistAndFlush())
                                .subscribe().with(item -> LOGGER.info("Something happened"), failure -> LOGGER.info("Something bad happened"));
                    }
                    return null;
                }).subscribe().with(o -> {
                });
    }

当我运行应用程序时,它没有给出任何错误,日志显示发生了一些事情,数据库创建了表,但是它没有插入任何东西。我以不同的方式尝试过它,但是,我没有成功地让它像我希望的那样工作。

4

2 回答 2

1

根据@Haroon 的回答和@Clement 的评论,我做了以下

  • 删除了@ReactiveTransactional,因为我的方法返回 void 并且不在 REST 边界上
  • 当我删除注释时,我需要使用 Panache.withTransaction 方法
  • 最后在我订阅的方法中

需要注意的是,我将 @Haroon 答案中的 transformToUniAndMerge 更改为 transformToUniAndConcatenate 以保持角色的顺序。

public void seedRoles() {
        Role.existsRoleSeed()
                .onItem().transformToMulti(exists -> {
                    if (!exists) {
                        return Multi.createFrom().items(Role.UserRole.values());
                    } else {
                        return Multi.createFrom().nothing();
                    }
                })
                .map(userRole -> Role.builder().name(userRole).build())
                .onItem().transformToUniAndConcatenate(role -> Panache.withTransaction(role::persist))
                .subscribe().with(subscription -> LOGGER.infov("Persisting: {0}", subscription));
    }
于 2021-09-24T07:25:34.827 回答
0

没有测试过这个。但这应该给你一些想法。

Multi<Role> savedRoles = Role.existsRoleSeed()
                                .onItem().transformToMulti(exists -> {
                                    if (!exists) {
                                        return Multi.createFrom().items(Role.UserRole.values());
                                    }
                                    return Multi.createFrom().nothing();
                                })
                                .map(userRole -> Role.builder().name(userRole).build())
                                .onItem().transformToUniAndMerge(role -> Panache.<Role>withTransaction(role::persist));

于 2021-09-20T13:51:45.810 回答