【问题标题】:Spring: How to return all objects with joined references of an entity by default with CrudRepositorySpring:默认情况下,如何使用 CrudRepository 返回具有实体连接引用的所有对象
【发布时间】:2020-03-11 16:36:04
【问题描述】:

我有一个产品表

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Product extends AuditModel {

    @Id
    @SequenceGenerator(name="optimized-sequence",sequenceName = "seq_product")
    private Integer id;
    private String sku;
    private String description;
    @NotNull
    private String name;

    *** 
    ***
    ***   

    @ManyToOne(optional = true)
    @JoinColumn(name = "category_id")
    @OnDelete(action = OnDeleteAction.NO_ACTION)
    private Category category;

    @ManyToOne(optional = true)
    @JoinColumn(name = "manufacturer_id")
    @OnDelete(action = OnDeleteAction.NO_ACTION)
    private Manufacturer manufacturer;

    @OneToMany(mappedBy = "product")
    private List<OrderProduct> orderProducts;

}

还有一个 CrudRepository

public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {

    Product findFirstBydescription(@Param("description")String description);

}

当我调用端点 /products 默认情况下我会得到一个这样的所有产品的列表

{
  "_embedded" : {
    "products" : [ {
      "createdAt" : "2019-11-15T08:56:23.393+0000",
      "updatedAt" : "2019-11-15T08:56:23.393+0000",
      "id" : 802,
      "sku" : null,
      "name" : " product 1",
      "description" : "description one",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/products/802"
        },
        "product" : {
          "href" : "http://localhost:8080/api/products/802{?projection}",
          "templated" : true
        },
        "manufacturer" : {
          "href" : "http://localhost:8080/api/products/802/manufacturer"
        },
        "orderProducts" : {
          "href" : "http://localhost:8080/api/products/802/orderProducts"
        },
        "category" : {
          "href" : "http://localhost:8080/api/products/802/category"
        }
      }
    }, .......

我怎样才能在 json 对象产品中调用默认端点 /products 来获取相关对象(Catefory、Manufacturer...)?

谢谢

【问题讨论】:

  • 我不明白你的问题

标签: java json spring hibernate


【解决方案1】:

如果我的理解正确,您应该在 @ManyToOne 或 @OneToOne 注释中使用 FetchType.EAGER 策略从数据库中获取所有相关数据。

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private Category category;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "manufacturer_id")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private Manufacturer manufacturer;

@OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<OrderProduct> orderProducts;

【讨论】:

  • Spring-jpa creates the query using the entity manager, and Hibernate will ignore the fetch mode if the query was built by the entity manager.@oguzhan00
【解决方案2】:

您可能希望使用FETCH JOIN 重写您的查询:

@Query("SELECT p FROM Product p JOIN FETCH p.category JOIN FETCH p.manufacturer JOIN FETCH p.orderProducts WHERE p.description = :description")
Product findFirstByDescription(@Param("description") String description);

它将急切地获取产品的关联。

请注意,在这种情况下,您应该延迟获取关联(即将关联注释的 fetch 参数设置为 EAGER)。

【讨论】:

  • 对不起,但不是那个查询。我想获取 CrudRepository 默认公开的默认 endponint /products 中的所有相关对象
【解决方案3】:

Spring Data Rest 无法实现

你的问题不是很清楚,但据我所知,我假设你使用Spring Data Rest 来公开你的数据。

正如this answer中所说的

Spring Data REST 使用Spring HATEOAS 自动暴露 Spring Data 存储库管理的实体的资源和 利用超媒体方面进行分页、链接实体等。

问题是,HATEOAS 背后的主要概念之一是discovery mechanism。这意味着使用 HATEOAS API,您将无法对您的资源进行“懒惰的展示”,这违反了 HATEOAS 的理念。

这就是为什么我认为如果你真的想要相关的对象,你应该避免Spring Data Rest,它不符合你的需求。

相反,您可以制作自己的控制器。您将失去 Spring Data Rest 提供的功能,而 CRUD 操作已经为每个实体实现。但是您将拥有更大的数据灵活性,并且能够通过 JSON 响应中的相关实体公开数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 2011-04-17
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    相关资源
    最近更新 更多