Quarkus:如何将方法从命令式更改为反应式
Quarkus: How to change a method from imperative to reactive
我构建了一个小的 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
}
}
现在在我的服务中(命令式)我执行以下操作:
Role.class
public static Boolean existsRoleSeed(){
return Role.count() > 0;
}
RoleService.class
@Transactional
public void seedRoles() {
if (!Role.existsRoleSeed()) {
for(Role.UserRole userRole: Role.UserRole.values()){
Role role = Role.builder()
.name(userRole)
.build();
role.persist();
}
}
}
这显然会在数据库中注册 UserRole 枚举中的所有角色,并且它工作正常。我想要实现的是复制此方法,但使用反应形式。这些是我在代码中所做的更改
Role.class
public static Uni<Boolean> existsRoleSeed() {
return Role.count().map(x -> x > 0);
}
RoleService.class
@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 -> {
});
}
当我 运行 应用程序时,它没有给出任何错误,日志显示发生了一些事情,数据库创建了 table,但是它没有插入任何东西。我尝试过不同的方法,但是,我没有成功地让它像我希望的那样工作。
还没有测试过这个。但这应该会给你一些想法。
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));
根据@Haroon 的回答和@Clement 的评论,我做了以下操作
- 删除了 @ReactiveTransactional 作为我的方法 returns 无效并且不在 REST 边界上
- 因为我删除了注释,所以我需要使用 Panache.withTransaction 方法
- 最后在方法中我订阅了 multi
请注意,我将 transformToUniAndMerge 从 @Haroon 的回答更改为 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));
}
我构建了一个小的 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
}
}
现在在我的服务中(命令式)我执行以下操作:
Role.class
public static Boolean existsRoleSeed(){
return Role.count() > 0;
}
RoleService.class
@Transactional
public void seedRoles() {
if (!Role.existsRoleSeed()) {
for(Role.UserRole userRole: Role.UserRole.values()){
Role role = Role.builder()
.name(userRole)
.build();
role.persist();
}
}
}
这显然会在数据库中注册 UserRole 枚举中的所有角色,并且它工作正常。我想要实现的是复制此方法,但使用反应形式。这些是我在代码中所做的更改
Role.class
public static Uni<Boolean> existsRoleSeed() {
return Role.count().map(x -> x > 0);
}
RoleService.class
@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 -> {
});
}
当我 运行 应用程序时,它没有给出任何错误,日志显示发生了一些事情,数据库创建了 table,但是它没有插入任何东西。我尝试过不同的方法,但是,我没有成功地让它像我希望的那样工作。
还没有测试过这个。但这应该会给你一些想法。
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));
根据@Haroon 的回答和@Clement 的评论,我做了以下操作
- 删除了 @ReactiveTransactional 作为我的方法 returns 无效并且不在 REST 边界上
- 因为我删除了注释,所以我需要使用 Panache.withTransaction 方法
- 最后在方法中我订阅了 multi
请注意,我将 transformToUniAndMerge 从 @Haroon 的回答更改为 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));
}