12.3 编写反应式的MongoDB repository
12.3.1 启用Spring Data MongoDB
- 添加依赖
如果需要非反应式则添加:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>
反应式则添加:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb-reactive</artifactId></dependency>
添加嵌入式的MongoDB
<dependency><groupId>de.flapdoodle.embed</groupId><artifactId>de.flapdoodle.embed.mongo</artifactId></dependency>
如果是生产环境,则不使用嵌入式数据库,还需要配置几个属性:
spring:data:mongodb:host: xxxxport: 27018username: xxxxpassword: xxxxdatabase: xxxx
12.3.2 将领域对象映射为文档
- @Id: 将某个属性指明为文档的ID
- @Document: 将领域类型声明为要持久化到MongoDB中的文档
@Field: 指定某个属性持久化到文档中的字段名称
@Data@RequiredArgsConstructor@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)@Document(collection = "ingredients")public class Ingredient {@Idprivate final String id;private final String name;private final Type type;public static enum Type {WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE}}
@Id可以用到任意Serializable类型的字段上,包括String和Long @Document(collection = “ingredients”): 如果没有特别指定,则会持久化到类名首字母小写(ingredient)的集合中,可以通过collection属性来改变这种行为
@Data@Documentpublic class Taco {@Idprivate String id;@NotNull@Size(min = 5, message = "name must be at least 5 characters long")private String name;private Date createdAt = new Date();@Size(min = 1, message = "You must choose at least 1 ingredient")private List<Ingredient> ingredients;}
@Data@Documentpublic class Order implements Serializable {private static final long serialVersionUID = 1L;@Idprivate String id;private Date placedAt = new Date();@Field("customer")private User user;private String deliveryName;private String deliveryStreet;private String deliveryCity;private String deliveryState;private String deliveryZip;private String ccNumber;private String ccExpiration;private String ccCVV;private List<Taco> tacos = new ArrayList<>();public void addDesign(Taco design) {this.tacos.add(design);}}
12.3.3 编写反应式的MongoDB repository接口
有两种接口选择:ReactiveCrudRepository和ReactiveMongoRepository
他们之间的区别在于:ReactiveMongoRepository提供多个特殊的insert()⽅法,它们针对新⽂档的持久化进⾏了优化,⽽ReactiveCrudRepository依赖save()⽅法来保存新⽂档和已有的⽂档
在数据库初始化完成之后,我们不会频繁地创建配料的⽂档,甚⾄有可能永远不会这样做。因此, ReactiveMongoRepository提供的优化没有太多的⽤处,我们可以让 IngredientRepository扩展ReactiveCrudRepository:
public interface IngredientRepository extends ReactiveCrudRepository<Ingredient, String> {}
为了将Taco持久化为MongoDB中的⽂档,我们定义另⼀个repository。 与配料⽂档不同,我们会频繁创建taco⽂档。因此,ReactiveMongoRepository优化过的insert()⽅法就很有价值了。
public interface TacoRepository extends ReactiveMongoRepository<Taco, String> {Flux<Taco> findByOrderByCreatedAt();}
public interface OrderRepository extends ReactiveMongoRepository<Order, String> {}
public interface UserRepository extends ReactiveMongoRepository<User, String> {Mono<User> findByUsername(String username);}
