我正在使用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,这个目标的任何解决方案?
答案 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);
}