簡體   English   中英

spring-data-jdbc:包含具有 1-n 關系的實體的查詢

[英]spring-data-jdbc: query containing entity with a 1-n relation

如何為包含 1-n 引用的實體編寫查詢?

基於spring-data-jdbc示例,我將使用以下單元測試對其進行解釋:

@Test
public void customQuery_ReferenceMultipleInstances() {
  // prepare
  LegoSet smallCar = createLegoSet("Small Car 01", 5, 12);
  smallCar.setManual(new Manual("Just put all the pieces together in the right order", "Jens Schauder"));
  smallCar.addModel("suv", "SUV with sliding doors.");
  smallCar.addModel("roadster", "Slick red roadster.");
  repository.save(smallCar);

  // execute
  List<LegoSet> actual = repository.findByName("Small Car 01");
  Iterable<LegoSet> compare = repository.findAll();

  // verify
  assertThat(actual).as("same number of lego sets").hasSize(Lists.newArrayList(compare).size());
  assertThat(actual.get(0).getModels()).as("same number of models").hasSize(Lists.newArrayList(compare).get(0).getModels().size());
  assertThat(actual.get(0).getModels().get(0)).as("model must not be null").isNotNull();
  assertThat(actual.get(0).getModels().get(0).getName()).as("model must have a name").isNotEmpty();
}

這模擬了一個引用 2 個ModelLegoSet repository.findByName()用自定義查詢注釋; repository.findAll()CrudRepository的標准 spring-boot-data 方法(僅供參考)。

版本 1 中的自定義查詢:

@Query("SELECT ls.id, ls.name, ls.min_age, ls.max_age, " +
      "h.handbuch_id AS manual_handbuch_id, h.author AS manual_author, h.text AS manual_text " +
      "FROM lego_set ls JOIN handbuch h ON ls.id = h.handbuch_id " +
      "WHERE name = :name")
List<LegoSet> findByName(@Param("name") String name);

在此版本中,測試失敗 w/

java.lang.AssertionError: [model must not be null] 
Expecting actual not to be null

好的,之后我將另一個JOIN添加到model中:

@Query("SELECT ls.id, ls.name, ls.min_age, ls.max_age, " +
      "h.handbuch_id AS manual_handbuch_id, h.author AS manual_author, h.text AS manual_text, " +
      "m.* " +
      "FROM lego_set ls JOIN handbuch h ON ls.id = h.handbuch_id " +
      "JOIN model m ON ls.id = m.lego_set " +
      "WHERE name = :name")
List<LegoSet> findByName(@Param("name") String name);

現在測試失敗了/

java.lang.AssertionError: [same number of lego sets] 
Expected size:<1> but was:<2> in:
<[LegoSet(id=1, name=Small Car 01, minimumAge=P5Y, maximumAge=P12Y, manual=Manual(id=1, author=Jens Schauder                                                                                       , text=Just put all the pieces together in the right order), models={suv=Model(name=suv, description=SUV with sliding doors.), roadster=Model(name=roadster, description=Slick red roadster.)}),
    LegoSet(id=1, name=Small Car 01, minimumAge=P5Y, maximumAge=P12Y, manual=Manual(id=1, author=Jens Schauder  

那么我該如何正確編寫該查詢呢?

第一個查詢實際上是正確的,並且工作正常。

問題出在你的測試中。 models是一個Map ,但是你把它當作一個List來編譯,因為列表索引也是一個有效的映射鍵。

如果您像這樣更改測試中的最后兩個斷言,它們將會成功:

assertThat(actual.get(0).getModels().get("suv")).as("model must not be null").isNotNull();
assertThat(actual.get(0).getModels().get("suv").getName()).as("model must have a name").isNotEmpty();
// ----------------------------------------^

另一種方法是使用第二個查詢,但使用自定義ResultSetExtractor將多個模型的多行收集到單個LegoSet中。

我處於類似情況,但我看不出我的情況有什么不同。

我有三個模型: Client: id, name.. Project: id, name, clientId, List ProjectMember

這是我的編碼查詢

  @Query("""
       select
          project.id,
          project.legacy_id,
          project.code,
          project.client_id,
          project.is_archived,
          project.name,
          project.budget_type,
          project.hours_budget_max,
          project.money_budget_max
       from project
       join client on client.id = project.client_id
       where client.name ilike '%:name%'
      """)
  List<Project> findByClientNameContainingIgnoreCase(final String name);

如您所見,我正在尋找客戶名稱(使用連接)匹配模式的項目。

手動執行請求會給我預期的結果。 但是通過 spring data jdbc 沒有給我任何結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM