在春季一对多实体关系不获取数据
Posted
技术标签:
【中文标题】在春季一对多实体关系不获取数据【英文标题】:In spring One To Many entity relationship is not fetching data 【发布时间】:2020-01-22 00:55:46 【问题描述】:我有一个简单的场景,其中 User 和 Skill 之间存在关系, 意味着一个用户有很多技能,所以我尝试了:
用户
@Data
@NoArgsConstructor
@Entity
@EqualsAndHashCode
public class User
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
@OneToMany(mappedBy = "user")
private List<Skill> skills;
技能
@Data
@NoArgsConstructor
@Entity
@EqualsAndHashCode
public class Skill
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String skillTitle;
@ManyToOne
@JoinColumn(name="user_id")
private User user;
用户存储库
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long>
List<User> findByName(@Param("name") String name);
技能库
@RepositoryRestResource(collectionResourceRel = "skills", path = "skills")
public interface SkillRepository extends CrudRepository<Skill, Long>
通过以上所有内容,我可以在例如 url http://localhost:8085/users/1
得到响应
"name": "Root",
"_links":
"self":
"href": "http://localhost:8085/users/1"
,
"user":
"href": "http://localhost:8085/users/1"
,
"skills":
"href": "http://localhost:8085/users/1/skills"
问题不是我不知道为什么没有获取技能列表,为什么只获取了这个
"skills":
"href": "http://localhost:8085/users/1/skills"
不是与user/1
相关的技能的完整列表。
更新
按照建议添加投影: 用户投影.java
@Projection(name = "inlineData", types=User.class)
public interface UserProjection
String getName();
List<Skill> getSkills();
UserRepository.java 是
@RepositoryRestResource(collectionResourceRel = "users", path = "users", excerptProjection = UserProjection.class)
public interface UserRepository extends PagingAndSortingRepository<User, Long>
List<User> findByName(@Param("name") String name);
回复是:
"name": "Root",
"_links":
"self":
"href": "http://localhost:8085/users/1"
,
"user":
"href": "http://localhost:8085/users/1?projection",
"templated": true
,
"skills":
"href": "http://localhost:8085/users/1/skills"
【问题讨论】:
你能把代码贴在你使用 findByUserId() 函数产生这个响应的地方吗? 这不就是 HATEOAS 的意义所在吗?点击链接可以看到用户的技能。 @CholNhial 单击该链接时不显示任何内容... 同样在 API 请求中,您正在发送 user1 但您正在为 user3 发布响应。 在第二个示例中,方法的名称是findByUserId
,但您将 skillId
作为参数传递。没事吧?
【参考方案1】:
响应是正确的,它按预期工作。 @RepositoryRestResource
遵循 HATEOAS 原则。 Spring documentation解释如下:
5.1.3。资源可发现性
HATEOAS 的核心原则是资源应该是可发现的 通过发布指向可用的链接的链接 资源...
通过向根 URL 发出请求...客户端可以从 返回的 JSON 对象,一组代表下一级的链接 客户端可用的资源...
您会获得代表资源的链接。要检索特定资源,您应该调用相应的 URL。您对用户 1 的回复意味着,如果您想获得用户 1 的技能,您应该调用 URL“http://localhost:8085/users/1/skills”。
如果您想象您有一个显示用户 1 属性的 html 页面,则更容易理解。此页面不直接显示技能,而是此页面包含指向技能页面的链接。只有当用户点击此链接时,才会加载技能页面。
了解HATEOAS很重要。
当然,有时 HATEOAS 不是最佳选择。但是这里我们不是在讨论 HATEOAS,而是解释 Spring 的这种实现背后的想法是什么。这种方法在许多情况下确实很有帮助。当您有 2 个具有 1-2 个属性的实体时,您可能会将这种方法视为矫枉过正。但是如果你有 30 - 50 个实体,每个实体有 3 - 5 个关系,每个关系包含 50 - 100 个其他实体,那么处理这样的数据模型可能会非常困难。而 HATEOAS 可以让它变得更容易。使用这种方法,您只是导航这些关系:加载一个实体、选择需要的关系、在这个关系上加载实体、选择需要的实体、在这个实体中选择需要的关系、加载这个关系或导航回其父实体通过父关系等。
【讨论】:
但是通过点击http://localhost:8085/users/1/skills
链接我得到skills[]
。有什么理由吗?以上是关于在春季一对多实体关系不获取数据的主要内容,如果未能解决你的问题,请参考以下文章