为什么我的 Hibernate `select` 查询超级慢?

Why are my Hibernate `select` queries super slow?

我在基于 Java 的 REST API 中使用 Hibernate。我使用 HQL 主要是因为它很简单。同样对于这个项目,我正在从主 table、其关联的 table、它们关联的 table 等加载数据。原因是在应用程序中,我在一个 JSON 字符串中拥有我需要的所有数据,而不是 运行 多个方法。

现在,看看下面的数据库结构。

让我们看一下代码。我将在 Stock 上使用 运行 getAll 方法。它将 return 我的所有 stock 数据 + 它的 product 数据 + 产品的 vehicle_model 数据 + 产品的 spare_part 数据

import beans.Stock;
import beans.TempStock;
import dao.SessionFactoryBuilder;
import java.util.Date;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class StockDAOImpl implements StockDAOInterface {

    private final SessionFactoryBuilder sessionFactoryBuilder = SessionFactoryBuilder.getInstance();

    @Override
    public List<Stock> getAllStock(Session session) {
        Query query = session.createQuery("FROM Stock s");
        List<Stock> list = (List<Stock>) query.list();
        return list;
    }

}

我只是发布数据抓取代码。

Hibernate 花了 40 多秒 return 我的数据!我还注意到我拥有的数据越多,花费的时间就越多。

下面是我的实体

股票

    public class Stock implements java.io.Serializable {
    
        private Integer idstock;
        @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
        private Product product;
        private int quantity;
        private Date dateCreated;
        private Date lastUpdated;
    
        public Stock() {
        }
    
        public Stock(Product product, int quantity) {
            this.product = product;
            this.quantity = quantity;
        }
    
        public Stock(Product product, int quantity, Date dateCreated, Date lastUpdated) {
            this.product = product;
            this.quantity = quantity;
            this.dateCreated = dateCreated;
            this.lastUpdated = lastUpdated;
        }
    
        public Integer getIdstock() {
            return this.idstock;
        }
    
        public void setIdstock(Integer idstock) {
            this.idstock = idstock;
        }
    
        public Product getProduct() {
            return this.product;
        }
    
        public void setProduct(Product product) {
            this.product = product;
        }
    
        public int getQuantity() {
            return this.quantity;
        }
    
        public void setQuantity(int quantity) {
            this.quantity = quantity;
        }
    
        public Date getDateCreated() {
            return this.dateCreated;
        }
    
        public void setDateCreated(Date dateCreated) {
            this.dateCreated = dateCreated;
        }
    
        public Date getLastUpdated() {
            return this.lastUpdated;
        }
    
        public void setLastUpdated(Date lastUpdated) {
            this.lastUpdated = lastUpdated;
        }
    
    }

车辆模型

public class VehicleModel implements java.io.Serializable {

    private Integer idvehicleModel;
    private String modelName;
    private String code;
    private boolean enable;

    public VehicleModel() {
    }

    public VehicleModel(String modelName, boolean enable) {
        this.modelName = modelName;
        this.enable = enable;
    }

    public Integer getIdvehicleModel() {
        return this.idvehicleModel;
    }

    public void setIdvehicleModel(Integer idvehicleModel) {
        this.idvehicleModel = idvehicleModel;
    }

    public String getModelName() {
        return this.modelName;
    }

    public void setModelName(String modelName) {
        this.modelName = modelName;
    }

    public boolean getEnable() {
        return this.enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

}

备件

public class SparePart implements java.io.Serializable {

    private Integer idsparePart;
    private String sparePartName;
    private String code;
    private boolean enable;

    public SparePart() {
    }

    public SparePart(String sparePartName, boolean enable) {
        this.sparePartName = sparePartName;
        this.enable = enable;
    }

    public Integer getIdsparePart() {
        return this.idsparePart;
    }

    public void setIdsparePart(Integer idsparePart) {
        this.idsparePart = idsparePart;
    }

    public String getSparePartName() {
        return this.sparePartName;
    }

    public void setSparePartName(String sparePartName) {
        this.sparePartName = sparePartName;
    }

    public boolean getEnable() {
        return this.enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

}

这只是 Hibernate 输出的 SQL 的一部分,您可以看到它试图通过单独执行 SQL 查询来从每个 table 中获取数据。

Hibernate: select stock0_.idstock as idstock1_5_, stock0_.idproduct as idproduc2_5_, stock0_.quantity as quantity3_5_, stock0_.date_created as date_cre4_5_, stock0_.last_updated as last_upd5_5_ from aaa.stock stock0_
Hibernate: select product0_.idproduct as idproduc1_0_0_, product0_.idspare_part as idspare_2_0_0_, product0_.idvehicle_model as idvehicl3_0_0_, product0_.unit_price as unit_pri4_0_0_, product0_.qrcode as qrcode5_0_0_, product0_.enable as enable6_0_0_, product0_.minimum_stock_level as minimum_7_0_0_, product0_.stock_reorder_level as stock_re8_0_0_ from aaa.product product0_ where product0_.idproduct=?
Hibernate: select sparepart0_.idspare_part as idspare_1_4_0_, sparepart0_.spare_part_name as spare_pa2_4_0_, sparepart0_.code as code3_4_0_, sparepart0_.enable as enable4_4_0_ from aaa.spare_part sparepart0_ where sparepart0_.idspare_part=?
Hibernate: select vehiclemod0_.idvehicle_model as idvehicl1_10_0_, vehiclemod0_.model_name as model_na2_10_0_, vehiclemod0_.code as code3_10_0_, vehiclemod0_.enable as enable4_10_0_ from aaa.vehicle_model vehiclemod0_ where vehiclemod0_.idvehicle_model=?
Hibernate: select product0_.idproduct as idproduc1_0_0_, product0_.idspare_part as idspare_2_0_0_, product0_.idvehicle_model as idvehicl3_0_0_, product0_.unit_price as unit_pri4_0_0_, product0_.qrcode as qrcode5_0_0_, product0_.enable as enable6_0_0_, product0_.minimum_stock_level as minimum_7_0_0_, product0_.stock_reorder_level as stock_re8_0_0_ from aaa.product product0_ where product0_.idproduct=?
Hibernate: select sparepart0_.idspare_part as idspare_1_4_0_, sparepart0_.spare_part_name as spare_pa2_4_0_, sparepart0_.code as code3_4_0_, sparepart0_.enable as enable4_4_0_ from aaa.spare_part sparepart0_ where sparepart0_.idspare_part=?
Hibernate: select vehiclemod0_.idvehicle_model as idvehicl1_10_0_, vehiclemod0_.model_name as model_na2_10_0_, vehiclemod0_.code as code3_10_0_, vehiclemod0_.enable as enable4_10_0_ from aaa.vehicle_model vehiclemod0_ where vehiclemod0_.idvehicle_model=?

如果这是正常的 SQL 这将使用联接。我该如何解决这个问题并尽快获取数据?更重要的是,有什么方法可以告诉 Hibernate 运行 将查询作为一个单元,并使用连接或其他方式?

答案是使用连接。

select s from Stock s join fetch s.product p 
join fetch p.sparePart sp
join fetch p.vehicleModel v