在Spring Boot应用程序中,我有两个实体Requirement和Product。需求与产品具有一对多关系。
在产品回购接口中,我有一个简单的查询方法,该方法可获取具有给定require_id的产品列表。这是代码:
interface ProductRepo: JpaRepository<Product, Int>{
fun findProductsByRequirement_Id(id:Int) : List<Product>
}
但是,当从Rest Controller调用此方法时,我可以看到,与每个产品一起,hibernate返回的是对应的需求对象,而不仅仅是request_id。它不止于此,它还返回与JSON结果中的需求对象关联的所有异物(交易和销售)。
我已经在application.properties文件中将此选项设置为“ spring.jpa.properties.hibernate.show_sql = true”,每次调用该查询方法时,我在控制台中都会看到Hibernate不断调用许多复杂的外部联接查询甚至我都没有要求。我认为,当我不需要所有这些异物时,这会消耗不必要的资源。
以下是休眠在后台运行的sql查询:
休眠:将requiremen0_.id选择为id1_8_0_,将requiremen0_.deal_id选择为 deal_id4_8_0_,requiremen0_.requirement_total与requirem2_8_0_, requiremen0_.sale_id为sale_id5_8_0_,requiremen0_.title为 title3_8_0_,deal1_.id为id1_4_1_,deal1_.account_id为 account_7_4_1_,以crm_cust8_4_1_的身分交易1..crm_customer_id, deal1_.exp_closing_date为exp_clos2_4_1_,deal1_.requirement_title为 requirem3_4_1_,deal1_.sales_value为sales_va4_4_1_,deal1_.stage为 stage5_4_1_,deal1_.type为type6_4_1_,deal1_.user_id为 user_id9_4_1_,account2_.id为id1_0_2_,account2_.address为 地址2_0_2_,帐户2_.crm_customer_id作为crm_cust9_0_2_, account2_.email为电子邮件3_0_2_,account2_.key_person为 key_pers4_0_2_,account2_.name为name5_0_2_,account2_.phone为 电话6_0_2_,帐户2_.status为状态7_0_2_,帐户2_。类型为 type8_0_2_,account2_.user_id为user_id10_0_2_,crmcustome3_.id为 id1_2_3_,crmcustome3_.address作为地址2_2_3_,crmcustome3_.email作为 email3_2_3_,crmcustome3_.key_person作为key_pers4_2_3_, crmcustome3_.name为name5_2_3_,crmcustome3_.number_of_users为 number_o6_2_3_,crmcustome3_.phone作为phone7_2_3_, crmcustome3_.subscription_type作为subscrip8_2_3_, crmcustome3_.validity_exp_date为validity9_2_3_,user4_.id为 id1_11_4_,user4_.crm_customer_id作为crm_cust8_11_4_, user4_.designation为designat2_11_4_,user4_.hierarchy_level为 hierarch3_11_4_,user4_.logged_in作为logging_i4_11_4_,user4_.login_id 作为login_id5_11_4_,user4_.login_pw作为login_pw6_11_4_,user4_.name作为 名称7_11_4_,sale5_.id为id1_9_5_,sale5_.crm_customer_id为 crm_cust4_9_5_,sale5_.deal_id作为deal_id5_9_5_,sale5_.sales_date作为 sales_da2_9_5_,sale5_.sales_value作为sales_va3_9_5_,sale5_.user_id 作为user_id6_9_5_,crmcustome6_.id作为id1_2_6_,crmcustome6_.address作为 地址2_2_6_,crmcustome6_.email作为电子邮件3_2_6_, crmcustome6_.key_person为key_pers4_2_6_,crmcustome6_.name为 name5_2_6_,crmcustome6_.number_of_users作为number_o6_2_6_, crmcustome6_.phone为phone7_2_6_,crmcustome6_.subscription_type为 subscrip8_2_6_,crmcustome6_.validity_exp_date作为有效期9_2_6_, deal7_.id为id1_4_7_,Deal7_.account_id为account_7_4_7_, deal7_.crm_customer_id为crm_cust8_4_7_,Deal7_.exp_closing_date为 exp_clos2_4_7_,deal7_.requirement_title为requirem3_4_7_, deal7_.sales_value作为sales_va4_4_7_,deal7_.stage作为stage5_4_7_, deal7_.type为type6_4_7_,Deal7_.user_id为user_id9_4_7_,user8_.id 作为id1_11_8_,user8_.crm_customer_id作为crm_cust8_11_8_, user8_.designation为designat2_11_8_,user8_.hierarchy_level为 hierarch3_11_8_,user8_.logged_in作为logging_i4_11_8_,user8_.login_id 作为login_id5_11_8_,user8_.login_pw作为login_pw6_11_8_,user8_.name作为 来自需求requirename0_的name7_11_8_左外部加入交易 对requiremen0_.deal_id = deal1_.id的Deal1_左外部加入帐户 deal1_.account_id = account2_.id上的account2_左外部联接 在deal1_.crm_customer_id = crmcustome3_.id上的crm_customers crmcustome3_ 左外部加入用户user4_ on deal1_.user_id = user4_.id左外部 在requiremen0_.sale_id = sale5_.id上左加入外部销售 crm_customers crmcustome6_特价5_.crm_customer_id = crmcustome6_.id 左外加入交易Deal7_待售中5_.deal_id = deal7_.id左外 加入用户user8_ on sale5_.user_id = user8_.id,其中requiremen0_.id =?
如何避免这种情况?
以下是产品和需求的实体类:
package com.ksk.crmserver.Model
import com.fasterxml.jackson.annotation.JsonIgnore
import javax.persistence.*
@Entity
@Table(name = "requirements")
data class Requirement(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int = 0,
@Column(name = "title")
val title: String = "",
@OneToMany(mappedBy = "requirement")
@JsonIgnore
val products: List<Product>? = null,
@Column(name = "requirement_total")
val requirementTotal: Int = 0,
@ManyToOne
var deal: Deal? = null,
@ManyToOne
val sale: Sale?=null
)
package com.ksk.crmserver.Model
import javax.persistence.*
@Entity
@Table(name = "products", indexes = [Index(name = "idx_product", columnList = "name")])
data class Product(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int = 0,
val name: String = "",
val description: String? = "",
@Column(name = "unit_cost")
val unitCost: Double = 0.0,
@Column(name = "qty")
val qty: Double? = 0.0,
val unit: String? = "",
@Column(name = "total_Cost")
val totalCost: Double? = 0.0,
@Column(name = "profit_margin")
val profitMargin: Double? = 0.0,
val profit: Double? = 0.0,
@Column(name = "vat_percentage")
val vatPercentage: Double? = 0.0,
val vat: Double? = 0.0,
@Column(name = "total_price")
val totalPrice: Double? = 0.0,
@ManyToOne
@JoinColumn(name = "requirement_id")
val requirement: Requirement? = null
)
编辑: 我尝试使用EntityManager.getReference来获取Requirement Object的实例。但它仍在运行很长的SQL查询,以便从数据库中按ID提取需求。这是我来自Product的RestController类的代码:
恐怕它仍在运行sql join查询。这是我的Rest Controller代码:
@RestController
@CrossOrigin
class ProductRoute(val productRepo: ProductRepo, val requirementRepo: RequirementRepo) {
@Autowired
val entityManager: EntityManager?=null
@GetMapping("/get/productsByReqId")
fun getProductsByRequirementId(@RequestParam id: Int): List<Product> {
val requirement = this.entityManager?.getReference(Requirement::class.java, id) as Requirement
print("Done fetching the requirement")
return this.productRepo.findProductsByRequirement(requirement)
}
这是Hibernate正在运行的sql:
休眠:将requiremen0_.id选择为id1_8_0_,将requiremen0_.deal_id选择为 deal_id4_8_0_,requiremen0_.requirement_total与requirem2_8_0_, requiremen0_.sale_id为sale_id5_8_0_,requiremen0_.title为 title3_8_0_,deal1_.id为id1_4_1_,deal1_.account_id为 account_7_4_1_,以crm_cust8_4_1_的身分交易1..crm_customer_id, deal1_.exp_closing_date为exp_clos2_4_1_,deal1_.requirement_title为 requirem3_4_1_,deal1_.sales_value为sales_va4_4_1_,deal1_.stage为 stage5_4_1_,deal1_.type为type6_4_1_,deal1_.user_id为 user_id9_4_1_,account2_.id为id1_0_2_,account2_.address为 地址2_0_2_,帐户2_.crm_customer_id作为crm_cust9_0_2_, account2_.email为电子邮件3_0_2_,account2_.key_person为 key_pers4_0_2_,account2_.name为name5_0_2_,account2_.phone为 电话6_0_2_,帐户2_.status为状态7_0_2_,帐户2_。类型为 type8_0_2_,account2_.user_id为user_id10_0_2_,crmcustome3_.id为 id1_2_3_,crmcustome3_.address作为地址2_2_3_,crmcustome3_.email作为 email3_2_3_,crmcustome3_.key_person作为key_pers4_2_3_, crmcustome3_.name为name5_2_3_,crmcustome3_.number_of_users为 number_o6_2_3_,crmcustome3_.phone作为phone7_2_3_, crmcustome3_.subscription_type作为subscrip8_2_3_, crmcustome3_.validity_exp_date为validity9_2_3_,user4_.id为 id1_11_4_,user4_.crm_customer_id作为crm_cust8_11_4_, user4_.designation为designat2_11_4_,user4_.hierarchy_level为 hierarch3_11_4_,user4_.logged_in作为logging_i4_11_4_,user4_.login_id 作为login_id5_11_4_,user4_.login_pw作为login_pw6_11_4_,user4_.name作为 名称7_11_4_,产品5_.requirement_id为require13_5_5_, products5_.id为id1_5_5_,product5_.id为id1_5_6_, product5_.description为descript2_5_6_,products5_.name为 名称3_5_6_,产品5_。利润为利润4_5_6_, products5_.profit_margin为profit_m5_5_6_,product5_.qty为 qty6_5_6_,products5_.requirement_id为require13_5_6_, product5_.total_price为total_co7_5_6_,product5_.total_price为 total_pr8_5_6_,products5_.unit为unit9_5_6_,products5_.unit_cost为 unit_co10_5_6_,products5_.vat如vat11_5_6_, products5_.vat_percentage为vat_per12_5_6_,sale6_.id为id1_9_7_, sale6_.crm_customer_id为crm_cust4_9_7_,sale6_.deal_id为 deal_id5_9_7_,sale6_.sales_date作为sales_da2_9_7_,sale6_.sales_value 作为sales_va3_9_7_,sale6_.user_id作为user_id6_9_7_,crmcustome7_.id作为 id1_2_8_,crmcustome7_.address作为地址2_2_8_,crmcustome7_.email作为 email3_2_8_,crmcustome7_.key_person作为key_pers4_2_8_, crmcustome7_.name为name5_2_8_,crmcustome7_.number_of_users为 number_o6_2_8_,crmcustome7_.phone如phone7_2_8_, crmcustome7_.subscription_type作为subscrip8_2_8_, crmcustome7_.validity_exp_date为validity9_2_8_,deal8_.id为 id1_4_9_,deal8_.account_id作为account_7_4_9_,deal8_.crm_customer_id 作为crm_cust8_4_9_,deal8_.exp_closing_date作为exp_clos2_4_9_, deal8_.requirement_title为requirem3_4_9_,Deal8_.sales_value为 sales_va4_4_9_,deal8_.stage为stage5_4_9_,deal8_.type为 type6_4_9_,deal8_.user_id作为user_id9_4_9_,user9_.id作为id1_11_10_, user9_.crm_customer_id为crm_cust8_11_10_,user9_.designation为 designat2_11_10_,user9_.hierarchy_level作为hierarch3_11_10_, user9_.logged_in为logging_i4_11_10_,user9_.login_id为 login_id5_11_10_,user9_.login_pw为login_pw6_11_10_,user9_.name为 需求需求中的name7_11_10_来自左外部加入交易 对requiremen0_.deal_id = deal1_.id的Deal1_左外部加入帐户 deal1_.account_id = account2_.id上的account2_左外部联接 在deal1_.crm_customer_id = crmcustome3_.id上的crm_customers crmcustome3_ 左外部加入用户user4_ on deal1_.user_id = user4_.id左外部 在requiremen0_.id = products5_.requirement_id上加入产品products5_ 左外部加入sales sale6_ on requiremen0_.sale_id = sale6_.id 外连接crm_customers crmcustome7_上 sale6_.crm_customer_id = crmcustome7_.id左外加入交易Deal8_ sale6_.deal_id = deal8_.id向左外部加入用户user9_ sale6_.user_id = user9_.id其中requiremen0_.id =?
完成获取要求2019-02-16 21:01:00.341 INFO 80558- [nio-8080-exec-1] o.h.h.i.QueryTranslatorFactoryInitiator: HHH000397:使用ASTQueryTranslatorFactory
休眠:选择product0_.id作为id1_5_,选择product0_.description作为 descript2_5_,product0_.name为name3_5_,product0_.profit为 Profit4_5_,product0_.profit_margin为profit_m5_5_,product0_.qty为 qty6_5_,product0_.requirement_id为require13_5_, product0_.total_cost为total_co7_5_,product0_.total_price为 total_pr8_5_,product0_.unit为unit9_5_,product0_.unit_cost为 unit_co10_5_,product0_.vat为vat11_5_,product0_.vat_percentage为 来自产品product0_的vat_per12_5_,其中product0_.requirement_id =?
答案 0 :(得分:0)
您可以将ManyToOne关系的fetchType设置为Lazy(ManyToOne关系的默认值为Eager)。这样,Hibernate仅在调用被调用对象时才加载它们。 如果要让Hibernate返回Id而不是整个引用的对象,则可以在此处查找:Hibernate - Foreign keys instead of Entities