在春季,一对多实体关系不获取数据

时间:2019-09-21 04:28:19

标签: java spring-boot spring-data-jpa spring-data-rest

我有一个简单的场景,其中用户技能之间存在关联, 意味着一个用户有很多技能,所以我尝试了:

用户

@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;

}

UserRepository

@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
    List<User> findByName(@Param("name") String name);
}

SkillRepository

@RepositoryRestResource(collectionResourceRel = "skills", path = "skills")
public interface SkillRepository extends CrudRepository<Skill, Long>{

}

通过以上所有内容,我都可以通过以下网址获得回复:网址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相关的技能的完整列表。

更新

根据建议添加了投影: UserProjection.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"
        }
    }
}

1 个答案:

答案 0 :(得分:0)

响应正确,可以正常工作。 @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可以使它变得更加容易。使用这种方法,您可以导航这些关系:加载一个实体,选择所需的关系,在此关系上加载实体,选择所需的实体,在该实体中选择所需的关系,加载该关系,或导航回通过父级关系等其父实体。