【问题标题】:Spring Data JPA, query too slow, too many subquery instead joinSpring Data JPA,查询太慢,子查询太多反而加入
【发布时间】:2019-11-19 15:37:26
【问题描述】:

我有一个 REST 服务,它使用 Spring Data JPA 调用简单的findAll。问题是在控制台中记录了很多查询,所以我想 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(但我想我可以避免这种情况,因为这种关系是默认的)因为我总是需要这两个对象。 以下是Dis 必须在我的findAll 中获取的Prodotto 项目:

@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(),但上面的问题仍然存在(奇怪的是与Dis相关的接口,为接口Prodotto返回两个空值和TipoValidazione)。

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

【问题讨论】:

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


    【解决方案1】:

    您想要做的是带有查询的JOIN FETCH(有几种方法可以实现),这样hibernate 将与父实体一起获取子表行,而不是默认的@987654322 @询问。

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

    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();
    

    【讨论】:

    • 我在Dis类的2关系(tipoValidazioneprodotto)上添加了注释@Fetch(FetchMode.JOIN),但我仍然得到n+1查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多