【问题标题】:Spring-boot, one-to-many relationship in the same object (parent & childrens)Spring-boot,同一对象中的一对多关系(父母和孩子)
【发布时间】:2020-06-21 15:01:23
【问题描述】:

在我的 spring-boot 项目中,我想创建具有父值和子值的对象“菜单”:
- 菜单可以有一个父元素
- 菜单可以有一个或多个子元素

实体 Menu.java

@Entity
@Data @AllArgsConstructor @NoArgsConstructor
public class Menu implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany
    private List<Menu> childrens;

    @ManyToOne
    private Menu parent;

}

MenuDAO.java

@RepositoryRestResource
public interface MenuDAO extends JpaRepository<Menu, Long> {

}

DemoApplication.java 添加数据以使用 CommandLine Runner 进行测试:

  • Menu1(父级)
  • Sub-Menu1(Menu1 的子级)
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

   @Autowired
   MenuDAO menuDAO;

   public static void main(String[] args) {
       SpringApplication.run(DemoApplication.class, args);
   }

   @Override
   public void run(String... args) throws Exception {
       Menu m1 = menuDAO.save(new Menu(null,"Menu1",null,null));
       Menu m2 = menuDAO.save(new Menu(null,"Sub-Menu1",null,m1));

   }
}

但是当我通过休息服务调用获取父元素时,我得到了这个结果http://localhost:9090/menus/1

{
 "name" : "Menu1",
 "_links" : {
   "self" : {
     "href" : "http://localhost:9090/menus/1"
   },
   "menu" : {
     "href" : "http://localhost:9090/menus/1"
   },
   "childrens" : {
     "href" : "http://localhost:9090/menus/1/childrens"
   },
   "parent" : {
     "href" : "http://localhost:9090/menus/1/parent"
   }
 }
}

但我的要求是获取以下 JSON 格式的数据:

{
"name" : "Menu1",
"childrens" : [{
                 "name" : "Menu2"
              }], 
"parent" : NULL,
"_links" : {
  "self" : {
    "href" : "http://localhost:9090/menus/1"
  },
  "menu" : {
    "href" : "http://localhost:9090/menus/1"
  },
  "childrens" : {
    "href" : "http://localhost:9090/menus/1/childrens"
  },
  "parent" : {
    "href" : "http://localhost:9090/menus/1/parent"
  }
}
}

有什么建议吗?

【问题讨论】:

  • StackOverflow 应该是英文的

标签: hibernate spring-boot rest jpa entity-relationship


【解决方案1】:

在阅读Spring Data REST 参考指南的文档后,我终于有了答案
Spring Data REST 呈现您导出的域模型的默认视图。但如果我们可能出于各种原因需要更改该模型的视图,我们可以使用投影和摘录来提供简化和简化的资源视图。
在我的例子中,第一步是为我的实体 Menu 创建一个 Prejection 接口,并选择我想在 JSON 响应中找到的所有属性。

@Projection(name = "MenuProjection", types = Menu.class)
public interface MenuProjection {
    Long getId();

    String getName();

    Menu getParent();

    List<Menu> getChildrens();

}

第二步是在我的MenuRepository中添加带有Menu.Class值的RepositroyRestRessource注解的属性excerptProjection > 接口。
@RepositoryRestResource(excerptProjection = MenuProjection.class)
之前的 JSON 响应

{
  "_embedded" : {
    "menus" : [ {
      "name" : "cat_test1",
      "_links" : {
        "self" : {
          "href" : "http://localhost:9292/menus/1"
        },
        "menu" : {
          "href" : "http://localhost:9292/menus/1"
        },
        "parent" : {
          "href" : "http://localhost:9292/menus/1/parent"
        },
        "pages" : {
          "href" : "http://localhost:9292/menus/1/pages"
        },
        "children" : {
          "href" : "http://localhost:9292/menus/1/children"
        }
      }
    }, {
      "name" : "cat_test2",
      "_links" : {
        "self" : {
          "href" : "http://localhost:9292/menus/2"
        },
        "menu" : {
          "href" : "http://localhost:9292/menus/2"
        },
        "parent" : {
          "href" : "http://localhost:9292/menus/2/parent"
        },
        "pages" : {
          "href" : "http://localhost:9292/menus/2/pages"
        },
        "children" : {
          "href" : "http://localhost:9292/menus/2/children"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:9292/menus{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:9292/profile/menus"
    },
    "search" : {
      "href" : "http://localhost:9292/menus/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  }
}

带有投影的 JSON

{
  "_embedded" : {
    "menus" : [ {
      "name" : "cat_test1",
      "parent" : null,
      "id" : 1,
      "childrens" : [ {
        "name" : "cat_test2"
      } ],
      "_links" : {
        "self" : {
          "href" : "http://localhost:9292/menus/1"
        },
        "menu" : {
          "href" : "http://localhost:9292/menus/1{?projection}",
          "templated" : true
        },
        "childrens" : {
          "href" : "http://localhost:9292/menus/1/childrens{?projection}",
          "templated" : true
        },
        "parent" : {
          "href" : "http://localhost:9292/menus/1/parent{?projection}",
          "templated" : true
        },
        "pages" : {
          "href" : "http://localhost:9292/menus/1/pages"
        }
      }
    }, {
      "name" : "cat_test2",
      "parent" : {
        "name" : "cat_test1",
      },
      "id" : 2,
      "childrens" : [ ],
      "_links" : {
        "self" : {
          "href" : "http://localhost:9292/menus/2"
        },
        "menu" : {
          "href" : "http://localhost:9292/menus/2{?projection}",
          "templated" : true
        },
        "childrens" : {
          "href" : "http://localhost:9292/menus/2/childrens{?projection}",
          "templated" : true
        },
        "parent" : {
          "href" : "http://localhost:9292/menus/2/parent{?projection}",
          "templated" : true
        },
        "pages" : {
          "href" : "http://localhost:9292/menus/2/pages"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:9292/menus{?page,size,sort,projection}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:9292/profile/menus"
    },
    "search" : {
      "href" : "http://localhost:9292/menus/search"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  }
}

因此,使用 Spring Data Projection,我们可以在实体资源中包含数据字段。

【讨论】:

    猜你喜欢
    • 2016-05-13
    • 2018-02-12
    • 2022-06-10
    • 2021-02-22
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    相关资源
    最近更新 更多