You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot获取Contrat实体完整数据:Angular5缺失关联Project字段

问题:Angular5调用Spring Boot接口获取Contrat时缺少关联Project字段的解决方案

我现在从Angular5向Spring Boot发送GET请求,想要获取Contrat实体的全部元素,但返回结果里缺少前端需要的project字段,数据库里是存在对应关联数据的。相关代码和返回结果如下:

Contrat实体代码

@Entity @Data @AllArgsConstructor @NoArgsConstructor 
public class Contrat implements Serializable{ 
    @Id @GeneratedValue 
    private Long id; 
    private Date dateDebut ; 
    private Date dateFin ; 
    private boolean valid; 
    @ManyToOne @JoinColumn(name = "Id_Project") 
    @JsonBackReference(value="projet-contrat") 
    private Project project; 
    @ManyToOne @JoinColumn(name = "Id_AppUser") 
    @JsonBackReference(value="appuser-contrat") 
    private AppUser appUser; 
}

Contrat仓库代码

public interface ContratRepo extends JpaRepository<Contrat,Long> { 
    @Query("select from Contrat c where c.appUser = :userApp") 
    public Page<Contrat> chercherContrat(@Param("userApp") AppUser userApp , Pageable pageable); 
}

Angular中返回结果示例

{id: 1, dateDebut: 1526083200000, dateFin: 1526083200000}

请问是否需要发送两次GET请求分别获取两个实体数据,或是有更优的解决方法?


解决方案

完全不需要发送两次请求,有几种更优雅的方式可以让你在一次请求中拿到包含project关联数据的Contrat结果:

1. 调整JSON序列化注解

你在project字段上使用的@JsonBackReference注解,主要作用是避免实体间的循环引用,但同时也会把该字段排除在序列化输出之外。可以换成更灵活的@JsonIgnoreProperties来控制序列化:

@ManyToOne
@JoinColumn(name = "Id_Project")
@JsonIgnoreProperties("contrats") // 假设Project实体中有contrats集合字段,忽略它避免循环引用
private Project project;

这样Spring Boot返回的JSON就会包含完整的project数据(只要Project实体的字段没有被其他忽略注解限制)。

2. 使用JOIN FETCH主动加载关联数据

修改JPA查询语句,通过JOIN FETCH强制在查询Contrat的同时加载关联的Project,避免懒加载导致序列化时无法获取数据:

// 添加查询所有Contrat并附带Project的方法
@Query("SELECT c FROM Contrat c JOIN FETCH c.project")
List<Contrat> findAllWithProject();

// 对现有的chercherContrat方法进行改造
@Query("SELECT c FROM Contrat c JOIN FETCH c.project WHERE c.appUser = :userApp")
Page<Contrat> chercherContratWithProject(@Param("userApp") AppUser userApp, Pageable pageable);

⚠️ 注意:当JOIN FETCH和Pageable一起使用时,可能会出现重复数据的问题。如果遇到这种情况,可以先分页查询Contrat的id列表,再根据id批量查询带关联数据的实体,或者调整查询逻辑。

3. 利用JPA实体图(Entity Graph)精准控制加载

通过定义实体图,可以指定查询时需要加载的关联字段,既灵活又能避免不必要的性能开销:
首先在Contrat实体上定义实体图:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@NamedEntityGraph(name = "Contrat.withProject", attributeNodes = @NamedAttributeNode("project"))
public class Contrat implements Serializable{
    // 原有字段保持不变
}

然后在Repository方法上标注使用该实体图:

@EntityGraph(value = "Contrat.withProject")
List<Contrat> findAll();

@EntityGraph(value = "Contrat.withProject")
Page<Contrat> chercherContrat(@Param("userApp") AppUser userApp, Pageable pageable);

这种方式可以根据不同的业务需求定义多个实体图,按需加载关联数据,是比较推荐的方案。

总结来说,以上三种方法都能帮你在一次GET请求中获取包含Project字段的Contrat数据,不用拆分请求。优先推荐实体图或JOIN FETCH的方式,能更精准地控制数据加载,提升接口性能。

内容的提问来源于stack exchange,提问作者dEs12ZER

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:17:22