我目前正在尝试在 Spring Boot 中为已经处于开发阶段的应用程序实现 R2DBC - 不幸的是,这意味着我们的 DDL 不灵活,因为其他微服务依赖于此,反之亦然。R2DBC 的一个重要限制是不支持嵌套类。此外,它不支持 JPA,因为这会破坏全面非阻塞的目的。因此,所有这些有用的注释也不在表中。
我正在处理的类看起来像这样:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Stats {
@Id
StatsPK statsPK
@Column(stat_name)
String stat;
...
@Data
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public static class StatsPK implements Serializable {
@Column("store_id")
private Integer storeId;
@Column("empl_id")
private String emplId;
@Column("app_version")
private String appVersion;
}
}
Run Code Online (Sandbox Code Playgroud)
在研究了我的问题后,我找到了很多方法来计算复合键,包括上面示例中已经显示的内容(使用 @Embeddable 注释),使用自定义 PK 对象(类似,但会有使用为此目的设计的类的选项,例如 CompositeKeyHolder)、JPA @TableId(TableId.class) 注释,以及其他一些似乎不太有希望的注释。
所有这些选项似乎都在使用 JPA 或使用嵌套对象,这是我做不到的。我真的想不出绕过这些限制的方法。但由于我是初学者,我决定询问是否有人以前处理过这个问题。感谢任何反馈。
ID getId()其中一个接口是“org.springframework.data.domain.Persistable”,它是一个java接口,具有第3方lib中的方法。
另一个接口是 Kotlin 接口interface IdEntry { val id: String}。
现在我的业务入口需要实现这两个接口:
data class MyEntry(
override val id: String,
....// more properties
) : IdEntry, Persistable<String>
Run Code Online (Sandbox Code Playgroud)
我使用IntelliJ IDE编码,错误是:
Class 'MyEntry' is not abstract and does not implement abstract member
@Nullable public abstract fun getId(): String!
defined in org.springframework.data.domain.Persistable
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题?
我还尝试了下面的代码:(来自这里的想法)
data class MyEntry(
private val id: String,
....// more properties
) : IdEntry, Persistable<String> {
override fun getId() = id
...
}
Run Code Online (Sandbox Code Playgroud)
但这也失败了:
Cannot weaken access …Run Code Online (Sandbox Code Playgroud) 我是反应式编程的新手。我必须开发一个简单的 Spring Boot 应用程序来返回 json 响应,其中包含公司详细信息及其所有子公司和员工
创建了一个 Spring Boot 应用程序(Spring Webflux + Spring data r2dbc )
使用下面的数据库表来表示公司和子公司以及员工关系(这是公司和子公司的层次关系,其中一个公司可以有N个子公司,每个子公司可以有另外N个子公司等等)
以下是代表上述表格的 java 模型类
公司.java
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Company implements Serializable {
private int id;
private String name;
private String address;
@With
@Transient
private List<Company> subCompanies;
@With
@Transient
private List<Employee> employees;
}
Run Code Online (Sandbox Code Playgroud)
员工.java
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Employee implements Serializable {
@Id
private int id; …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 R2DBC 编写一些反应式后端,但遇到了我不太理解的事情。我不知道为什么,但 Spring 正在尝试更新条目而不是将其保存到数据库中。
我的用户模型:
@Table("user")
@NoArgsConstructor
@Data
public class User {
@Id
private String id;
private String username;
private String password;
public User(String id,String username,String password){
this.id = id;
this.username = username;
this.password=password;
}
Run Code Online (Sandbox Code Playgroud)
我的控制器:
@RestController
public class UserController {
` private final UserRepository userRepository`;
@Autowired
public UserController(UserRepository userRepository){
this.userRepository = userRepository;
}
@PostMapping("/create")
public Mono<User> createUser(@RequestBody User user){
return userRepository.save(user);
}
Run Code Online (Sandbox Code Playgroud)
当我使用如下输入向此端点发送 POST 请求时:
{“id”:“re”,“用户名”:“ehmmidk”,“密码”:“dsadsadsadsa”}
即使我的数据库中没有条目,它也会进行更新而不是保存。
我的架构如下所示:
CREATE TABLE user (
id VARCHAR(255) NOT NULL ,
username …Run Code Online (Sandbox Code Playgroud) 我在 postgresql 数据库中有一些限制(唯一的、外键...)。
我使用 spring data r2dbc 存储库:ReactiveCrudRepository
我想将DataIntegrityViolationException存储库的抛出转换为基于 的constraintNameinErrorDetails字段的自定义异常PostgresqlDataIntegrityViolationException。
但ExceptionFactory包含该类的类PostgresqlDataIntegrityViolationException是包私有的。所以我无法投射DataIntegrityViolationExceptionto的原因异常PostgresqlDataIntegrityViolationException。
constraintName当我捕获 时,访问 的最干净的方法是什么DataIntegrityViolationException?
(比解析异常消息更好的事情^^)
编辑 :
我以这个解决方案结束:
val DataIntegrityViolationException.pgErrorDetails: ErrorDetails
get() = when(val cause = this.cause) {
null -> error("cause should not be null")
else -> cause.javaClass
.getDeclaredField("errorDetails")
.apply { isAccessible = true }
.let { it.get(cause) as ErrorDetails }
}
Run Code Online (Sandbox Code Playgroud) 我正在使用 Spring data r2dbc,它不支持多对多映射。
表格:-
user
user_role
user_role_mapping
Run Code Online (Sandbox Code Playgroud)
像往常一样,一个用户可以有多个映射。
sql查询,
select * from user u, user_role_mapping urm, user_role ur 其中 u.user_id = :userId 和 u.org_id = :orgId 和 u.user_id = urm.user_id 和 ur.role_id = urm.role_id
在这里,我有一个模型对象,其中包含所有 3 个类的所有属性。在这里,由于用户具有多个角色,因此我获取多个记录,然后使用用户详细信息和角色列表构建单个记录。
型号类,
class User {
private long userId;
private String userName;
private List<String> roles;
}
Run Code Online (Sandbox Code Playgroud)
Spring r2dbc 是否有任何开箱即用的支持,它返回一个包含用户详细信息和List<String>角色的用户对象。
图书馆:
\n问题:\n我尝试使用 R2DBC (PostgreSQL) 批量插入,代码如下:
\n@Override\npublic Flux<Long> test(List<User> users) {\n return Mono.from(connectionFactory.create())\n .flatMapMany(c -> Mono.from(c.beginTransaction())\n .thenMany(Flux.fromIterable(users)\n .map(u -> {\n return Flux.from(c.createStatement("INSERT INTO public.users(name, age, salary) VALUES ($1, $2, $3)").returnGeneratedValues("id")\n .bind(0, u.getName())\n .bind(1, u.getAge())\n .bind(2, u.getSalary()).execute());\n })\n .flatMap(result -> result)\n .map(result -> result.map((row, meta) -> {\n return row.get("id", Long.class);\n }))\n .flatMap(Flux::from)\n .delayUntil(r -> c.commitTransaction())\n .doFinally((st) -> c.close())));\n}\nRun Code Online (Sandbox Code Playgroud)\n该代码将执行语句将用户插入数据库,然后获取生成的用户 ID。如果用户列表小于或等于 255,以上代码将按预期工作。当用户列表大于 255(256~)时,会出现以下异常:
\n[5b38a8c6-2] There was an …Run Code Online (Sandbox Code Playgroud) postgresql spring-webflux spring-data-r2dbc r2dbc r2dbc-postgresql
由于 R2DBC 是反应式且非阻塞的,我想了解在简单的 RESTful CRUD 服务中使用 R2DBC 的好处
假设 Spring Boot 应用程序使用下面的存储库公开 RESTful 服务
public interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> {
@Query("SELECT * FROM customer WHERE last_name = :lastname")
Flux<Customer> findByLastName(String lastName);
}
Run Code Online (Sandbox Code Playgroud)
该存储库是从服务调用的,结果需要在服务中进行转换,然后再返回到控制器。
Flux<Customer> customers = repository.findAll();
Run Code Online (Sandbox Code Playgroud)
为了访问完整的客户列表,我需要调用blockLast()Flux,这会使其阻塞并违背使用反应式组件的目的。
这是否意味着在这个简单的示例中使用 R2DBC 没有任何好处?我错过了什么吗?
Flux 是否只能用于异步订阅(其中 Flux 集合的处理发生在不同的线程中)?
我想将 postgresql 中的表中新创建的记录作为实时/连续流获取。可以使用spring r2dbc吗?如果是这样,我有什么选择?
谢谢
我正在尝试测试服务,但存储库始终为空。使用 JPA 存储库时,我从未遇到过此问题。我不确定它是否与 ReactiveCrudRepository 有关。有人遇到过这个问题吗?
@RunWith(MockitoJUnitRunner.class)
class UserTest {
@InjectMocks
private UserService underTest;
@Mock
private UserRepository userRepository;
@Mock
private AutoCloseable closeable;
@BeforeEach
public void init() {
closeable = MockitoAnnotations.openMocks(this);
}
@AfterEach
public void closeService() throws Exception {
closeable.close();
}
@Test
void getApplicableUsers() {
when(userRepository.findAll().collectList().block()).thenReturn(new ArrayList<>());
Set<User> expected = underTest.getUsers(getUser(), getUsers());
verify(underTest, times(1)).updateUsers(getUser(),expected);
}
}
Run Code Online (Sandbox Code Playgroud)
> error
>
> java.lang.NullPointerException
> at com.user.UserServiceTest.updateUsers(UserService.java:99)
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
> Method)
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.base/java.lang.reflect.Method.invoke(Method.java:566)
> at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
> …Run Code Online (Sandbox Code Playgroud) r2dbc ×7
java ×3
spring-data ×2
asynchronous ×1
kotlin ×1
mockito ×1
pojo ×1
postgresql ×1
spring ×1
unit-testing ×1