Java 在两个不同的ReactiveMongoRepository';在使用Spring数据MongoDB的事务中?
使用Spring Data MongoDB的反应式编程模型时,可以执行如下事务:Java 在两个不同的ReactiveMongoRepository';在使用Spring数据MongoDB的事务中?,java,spring,mongodb,spring-boot,spring-data-mongodb-reactive,Java,Spring,Mongodb,Spring Boot,Spring Data Mongodb Reactive,使用Spring Data MongoDB的反应式编程模型时,可以执行如下事务: Mono result=template.inTransaction() .execute(action->action.remove(查询(其中(“id”).is(“step-1”)),step.class)); 但是Spring Data MongoDB也支持“反应式存储库”,例如: public interface PersonRepository扩展了ReactiveMongoRepository 通过定
Mono result=template.inTransaction()
.execute(action->action.remove(查询(其中(“id”).is(“step-1”)),step.class));
但是Spring Data MongoDB也支持“反应式存储库”,例如:
public interface PersonRepository扩展了ReactiveMongoRepository
通过定位线查找的流量(点位置、距离);
}
及
public interface CarRepository扩展了ReactiveMongoRepository
通量查找年份(整数年);
}
我的问题是,考虑到您有
ReactiveMongoRepository
,您能否以某种方式利用MongoDB事务,例如在同一事务中同时插入Person
和CarRepository
(在本例中使用PersonRepository
)?如果是这样的话,您是如何做到的?我也一直在努力寻找解决方案,为Mongo DB&Spring Boot的反应式事务性支持提供解决方案
但幸运的是我自己发现了。虽然谷歌提供的东西很少有帮助,但这些都是非反应性的
重要注意事项-对于Spring boot 2.2.x,它工作得很好,但是对于Spring boot 2.3.x,它还有一些其他问题,包括内部重写和更改
- 您需要使用ReactiveMongoTransactionManager以及ReactiveMongoDatabaseFactory,最后的大部分细节,还需要共享相同的代码repo
- 为了让mongo db支持事务,我们需要确保db应该在副本模式下运行 我们为什么需要它?因为否则会出现如下错误:- 此客户端所连接的MongoDB群集不支持会话
- config包中的MongoConfiguration类是使事务正常工作的重要部分,可以使用到配置类的链接
- 主要部分是Bean
@Bean ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) { return new ReactiveMongoTransactionManager(dbFactory); }
- 为了检查代码事务性需求的工作情况,您可以通过服务包中的类UserService进行检查
@Configuration
public class MongoConfiguration extends AbstractMongoClientConfiguration {
@Autowired
private MongoProperties mongoProperties;
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
@Override
protected String getDatabaseName() {
return mongoProperties.getDatabase();
}
@Override
public MongoClient mongoClient() {
return MongoClients.create(mongoProperties.getUri());
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "roles")
@TypeAlias("role")
public class Role implements Persistable<String> {
@Id
private String id;
@Field("role_name")
@Indexed(unique = true)
private String role;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "users")
@JsonInclude(JsonInclude.Include.NON_NULL)
@TypeAlias("user")
public class User implements Persistable<String> {
@Id()
private String id;
@Field("username")
@Indexed(unique = true)
@JsonProperty("username")
private String userName;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@DBRef(lazy = true)
@JsonProperty("roles")
private List<Role> roles = new ArrayList();
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "user_profiles")
@JsonInclude(JsonInclude.Include.NON_NULL)
@TypeAlias("user_profile")
public class UserProfile implements Persistable<String> {
@Id
private String id;
@Indexed(unique = true)
private String mobile;
@Indexed(unique = true)
private String email;
private String address;
private String firstName;
private String lastName;
@DBRef
private User user;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
application.properties(与mongo db相关)
文档类
@Configuration
public class MongoConfiguration extends AbstractMongoClientConfiguration {
@Autowired
private MongoProperties mongoProperties;
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
@Override
protected String getDatabaseName() {
return mongoProperties.getDatabase();
}
@Override
public MongoClient mongoClient() {
return MongoClients.create(mongoProperties.getUri());
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "roles")
@TypeAlias("role")
public class Role implements Persistable<String> {
@Id
private String id;
@Field("role_name")
@Indexed(unique = true)
private String role;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "users")
@JsonInclude(JsonInclude.Include.NON_NULL)
@TypeAlias("user")
public class User implements Persistable<String> {
@Id()
private String id;
@Field("username")
@Indexed(unique = true)
@JsonProperty("username")
private String userName;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@DBRef(lazy = true)
@JsonProperty("roles")
private List<Role> roles = new ArrayList();
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "user_profiles")
@JsonInclude(JsonInclude.Include.NON_NULL)
@TypeAlias("user_profile")
public class UserProfile implements Persistable<String> {
@Id
private String id;
@Indexed(unique = true)
private String mobile;
@Indexed(unique = true)
private String email;
private String address;
private String firstName;
private String lastName;
@DBRef
private User user;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
角色类别
@Configuration
public class MongoConfiguration extends AbstractMongoClientConfiguration {
@Autowired
private MongoProperties mongoProperties;
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
@Override
protected String getDatabaseName() {
return mongoProperties.getDatabase();
}
@Override
public MongoClient mongoClient() {
return MongoClients.create(mongoProperties.getUri());
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "roles")
@TypeAlias("role")
public class Role implements Persistable<String> {
@Id
private String id;
@Field("role_name")
@Indexed(unique = true)
private String role;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "users")
@JsonInclude(JsonInclude.Include.NON_NULL)
@TypeAlias("user")
public class User implements Persistable<String> {
@Id()
private String id;
@Field("username")
@Indexed(unique = true)
@JsonProperty("username")
private String userName;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@DBRef(lazy = true)
@JsonProperty("roles")
private List<Role> roles = new ArrayList();
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "user_profiles")
@JsonInclude(JsonInclude.Include.NON_NULL)
@TypeAlias("user_profile")
public class UserProfile implements Persistable<String> {
@Id
private String id;
@Indexed(unique = true)
private String mobile;
@Indexed(unique = true)
private String email;
private String address;
private String firstName;
private String lastName;
@DBRef
private User user;
@CreatedDate
private ZonedDateTime created;
@LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
@Override
@JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
UserProfileApisController类
@Slf4j
@RestController
@RequestMapping("/apis/user/profile")
public class UserProfileApisController {
@Autowired
private UserService userService;
@PostMapping
public Mono<UserProfile> saveUserProfile(final @RequestBody UserRequest userRequest) {
return userService.saveUserAndItsProfile(userRequest);
}
}
@Slf4j
@RestController
@请求映射(“/api/user/profile”)
公共类UserProfileApisController{
@自动连线
私人用户服务;
@邮戳
公共Mono saveUserProfile(final@RequestBody UserRequest UserRequest){
返回userService.saveUserAndItsProfile(userRequest);
}
}
只是对公认的MongoDB副本集初始化答案的补充
final MongoDBContainer MongoDBContainer=新的MongoDBContainer(“mongo:4.2.8”);
我们可以通过“mongoDBContainer.start()”启动它,并通过“try with resources”或“mongoDBContainer.stop()”停止它
试试看(
//创建PSA MongoDBreplication集,然后自动关闭
最终MongoDbReplicaSet MongoDbReplicaSet=MongoDbReplicaSet.builder()
//具有2个工作节点
.replicaSetNumber(2)
//使用仲裁节点
.addArbiter(正确)
//为每个节点创建代理以模拟网络分区
.addToxiproxy(true)
.build()
) {
//开始吧
mongoDbReplicaSet.start();
assertNotNull(mongoDbReplicaSet.getReplicaSetUrl());
//做一些测试
}
有关于这个伴侣的帮助吗@JohanSorry,但我不记得我找到了解决方案。幸运的是,在给你发消息后,我发现了这一点,我很快会与你分享。看到答案了吗below@Johan我还在编辑的过程中。但是请仔细阅读我在回答中分享的细节谢谢@kakabali,但是您能在这里包含代码示例的要点吗?我认为这是stackoverflow答案的习惯,因为远程链接可能不再存在。
@Slf4j
@RestController
@RequestMapping("/apis/user/profile")
public class UserProfileApisController {
@Autowired
private UserService userService;
@PostMapping
public Mono<UserProfile> saveUserProfile(final @RequestBody UserRequest userRequest) {
return userService.saveUserAndItsProfile(userRequest);
}
}