为什么我的 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
我在基于 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