在spring数据中使用什么而不是fetch.EAGER?

时间:2018-05-25 01:22:21

标签: java spring hibernate spring-boot angular5

我正在使用spring-boot和angular5,我在春天有这个实体:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Contrat implements Serializable{

    @Id @GeneratedValue
    private Long id;
    private Date dateDebut ;
    private Date dateFin ;
    @ManyToOne
    @JoinColumn(name = "Id_Project")
    @JsonBackReference(value="projet-contrat")
    private Project project;

    @ManyToOne
    @JoinColumn(name = "Id_AppUser")
    @JsonBackReference(value="appuser-contrat")
    private AppUser appUser;
}

存储库:

public interface ContratRepo extends JpaRepository<Contrat,Long> {

    public Page<Contrat> findByAppUser(@Param("userApp") AppUser userApp, Pageable pageable);

}

由于fetch.lazy是默认值,当我尝试调用方法findByAppUser时,我得到结果:

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

这是正常的,我想要的是加载对象&#39; project&#39;存在于实体中,但我不想使用fetch.EAGER,这个目标的任何解决方案?

2 个答案:

答案 0 :(得分:1)

您的实体是一对多关系对象。如果您不使用EAGER,弹簧数据将获得没有相关成员对象的对象。如果你使用contract.getProject().getName()得到它,那么将发送另一个查询以获得该成员。

如果您记录SQL,则可以看到,将有2个查询。但是如果将字段设置为EAGER,则只有1个查询。你可以明显改善。

但你不应该永远使用EAGER。如果在90%的时间内,您只需要Contract对象,但不需要它的项目数据。得到这个是浪费时间。因为在SQL中,它将关联2个表并获取所有数据列。

所以,你应该根据你对这个实体的使用做出这个决定。

[根据评论更新]

您可以使用Query编写sql表达式。例如,我有一个方法来获取具有细节的实体:

    @Query("select s from Contract s left join fetch s.project pr where s.id = ?1 ")
    Contract findOneWithDetail(Long id);

如果我需要在一个sql中获取详细信息,我可以使用此方法。如果我不需要项目详细信息,我只需使用findOne(Long id),这是提供的界面。

而且,如果您只想获得一些列,则需要使用构造函数定义DTO,并编写如下所示的方法:

    @Query("SELECT NEW com.mypackage.dto.ContractDTO(s.id, s.name, s.status)  FROM Contract AS s WHERE s.status = ?1")
    List<ContractDTO> findDTOAllByStatus(String status);

答案 1 :(得分:0)

在您的repo方法中提供查询,例如(语法可能有误,只是告诉你这个想法)

 public interface ContratRepo extends JpaRepository<Contrat,Long> {

    @Query(query="from Contrat c left join fetch c.project " +
                  "where c.userApp = :userApp")
    public Page<Contrat> findByAppUser(@Param("userApp") AppUser userApp, Pageable pageable);

}