首页 > 解决方案 > Spring Data JPA,查询太慢,子查询太多反而加入

问题描述

findAll我有一个使用 Spring Data JPA调用简单的 REST 服务。问题是在控制台中记录了很多查询,所以我想 Spring Data 不是连接,而是对我的主类名为Dis.

我有一个主要实体,它必须只获取一些带有注释的数据@JsonView

@Entity
@NamedQuery(name="Dis.findAll", query="SELECT d FROM Dis d")
public class Dis implements Serializable {
    private static final long serialVersionUID = 1L;

    @JsonView(View.Summary.class)
    @Id
    @Column(name="id_dis")
    private Integer idDis;

    private byte[] logo;

    @JsonView(View.Summary.class)
    private String text;

    @JsonView(View.Summary.class)
    @JsonManagedReference
    //bi-directional many-to-one association to TipoValidazione
    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="validazione")
    private TipoValidazione tipoValidazione;

    //bi-directional many-to-one association to DisComune
    @OneToMany(mappedBy="dis")
    private List<DisComune> disComunes;

    //bi-directional many-to-one association to PdfDis
    @OneToMany(mappedBy="dis")
    private List<PdfDis> pdfDiss;

    @JsonView(View.Summary.class)
    @JsonManagedReference
    //bi-directional many-to-one association to Prodotto
    @OneToOne(mappedBy="dis", fetch=FetchType.EAGER)
    private Prodotto prodotto;

    //getter and setter
}

我设置FetchType.EAGER(但我想我可以避免这种情况,因为这种关系是默认的)因为我总是需要这两个对象。以下是必须在 my 中获取的Prodotto项目:DisfindAll

@Entity
@NamedQuery(name="Prodotto.findAll", query="SELECT p FROM Prodotto p")
public class Prodotto implements Serializable {
    private static final long serialVersionUID = 1L;

    @JsonView(View.Summary.class)
    @Id
    @Column(name="id_prodotto")
    private Integer idProdotto;

    @JsonView(View.Summary.class)
    @Column(name="cod_prodotto")
    private String codProdotto;

    @Column(name="id_classe")
    private Integer idClasse;


    @JsonBackReference
    //bi-directional many-to-one association to Dis
    @OneToOne
    @JoinColumn(name="id_dis")
    private Dis dis;

    //getter and setter
}

和类似的类TipoValidazione

@Entity
@Table(name="tipo_validazione")
@NamedQuery(name="TipoValidazione.findAll", query="SELECT t FROM TipoValidazione t")
public class TipoValidazione implements Serializable {
    private static final long serialVersionUID = 1L;

    @JsonView(View.Summary.class)
    @Id
    private String validazione;

    @JsonBackReference
    //bi-directional many-to-one association to Dis
    @OneToMany(mappedBy="tipoValidazione")
    private List<Dis> diss;

    //getter and setter
}

简单findAll的问题是产生很多子查询(我想每行一两个,而不是进行连接),所以它可以工作,但速度非常慢且不可用。

我尝试使用findBy()不带参数的 a 进行基于接口的投影,但上面的问题仍然存在(奇怪的是与 相关的接口,为接口和Dis返回两个空值)。ProdottoTipoValidazione

我该如何解决?我知道我可以编写一个自定义的 nativeQuery,但我试图避免这种解决方案。

标签: javaspring-bootspring-data-jpa

解决方案


你想要做的是JOIN FETCH你的查询(有几种方法可以实现这一点),以便休眠将与父实体一起获取子表行,而不是执行默认值,即n + 1查询。

以下是我知道的两种方法:

  1. 实现您自己的查询以包含JOIN FETCH
    @Override
    @Query(value = "SELECT distinct d" +
            "         FROM Dis d " +
            "              JOIN FETCH d.disComunes ")
    List<Dis> findAll();
  1. 创建一个@NamedEntityGraph可以将查询提示应用于您在实体中选择的所有查询的位置:
@Entity
@NamedEntityGraph(name = "Dis.detail", 
attributeNodes = {@NamedAttributeNode("tipoValidazione"),
        @NamedAttributeNode("prodotto")})
@NamedQuery(name="Dis.findAll", query="SELECT d FROM Dis d")
public class Dis implements Serializable {

在存储库中:

@Override
@EntityGraph(value = "Dis.detail" , type=EntityGraphType.FETCH)
List<Dis> findAll();

推荐阅读