【问题标题】:Eagerly load MongoDB @DBRef in Spring data's RepositoryRestResource在 Spring 数据的 RepositoryRestResource 中急切地加载 MongoDB @DBRef
【发布时间】:2017-04-13 14:04:54
【问题描述】:

我正在尝试使用RepositoryRestResourceRestTemplate 实现一个rest api

一切都很好,除了加载@DBRef's

考虑这个数据模型:

public class Order
{
   @Id
   String id;

   @DBRef
   Customer customer;

   ... other stuff
}

public class Customer
{
    @Id
    String id;

    String name;

    ...
}

以及以下存储库(与客户类似)

@RepositoryRestResource(excerptProjection = OrderSummary.class)
public interface OrderRestRepository extends MongoRepositor<Order,String>{}

其余 api 返回以下 JSON:

{
  "id" : 4,
  **other stuff**,
  "_links" : {
    "self" : {
      "href" : "http://localhost:12345/api/orders/4"
    },
    "customer" : {
      "href" : "http://localhost:12345/api/orders/4/customer"
    }
  }
}

如果由 resttemplate 正确加载,它将创建一个新的 Order 实例,其中 customer = null

是否可以在存储库端急切地解析客户并嵌入JSON?

【问题讨论】:

    标签: mongodb spring-boot spring-data-mongodb spring-data-rest


    【解决方案1】:

    在这种情况下急切地解析依赖实体很可能会引发N+1 database access problem。 我认为没有办法使用默认的 Spring Data REST/Mongo 存储库实现来做到这一点。

    这里有一些替代方案:

    1. 构造一个自己的自定义 @RestController 方法,该方法将访问数据库并构造所需的输出
    2. 使用Projections 填充相关集合中的字段,例如

      @Projection(name = "main", types = Order.class)
      public interface OrderProjection {
          ...
      
          // either
          @Value("#{customerRepository.findById(target.customerId)}")
          Customer getCustomer();
      
          // or
          @Value("#{customerService.getById(target.customerId)}")
          Customer getCustomer();
      
          // or
          CustomerProjection getCustomer();
      } 
      
      @Projection(name = "main", types = Customer.class)
      public interface CustomerProjection {
          ...
      }
      
    3. customerService.getById 可以使用缓存(例如使用 Spring @Cachable annotation)来减轻额外访问每个结果集记录的数据库的性能损失。

    4. 为您的数据模型添加冗余,并在创建/更新时将 Customer 对象字段的副本存储在 Order 集合中。

    在我看来,出现这种问题是因为 MongoDB 不太支持连接不同的文档集合(它的"$lookup" operator 与常见的 SQL JOIN 相比有很大的局限性)。 MongoDB docs also do not recommend 使用 @DBRef 字段,除非加入托管在不同服务器中的集合:

    除非您有令人信服的理由使用 DBRefs,否则请改用手动引用。

    这里还有一个类似的question

    【讨论】:

    • 我使用嵌套投影修复了它。这就像一个魅力。由于我只需要在检索单个订单时急切解决,因此查询量将是最少的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多