我看到很多帖子,其中Eager fetch在休眠状态下执行子表父表的左连接。但是当我使用springboot时,hibernate会触发单独的sql查询- 意味着一个针对父表的选择查询和一个针对子表的选择查询。为什么有区别?springboot是否进行了升级,或者我做错了什么?
以下是我正在使用的实体:
订单实体:
@Entity @Table(name="Ordertable", schema="cf_2583f365_c3c6_499a_a60d_138e7e7023eb") public class Order { @Id @Column(name = "ORDER_ID") @GeneratedValue(strategy=GenerationType.IDENTITY) private int orderId; @Column(name = "DAT_SRC_ID") private String dataSourceId; @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name = "ORDER_CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID") private Customer customer; }
客户实体:
@Entity @Table(name="Customer", schema="cf_2583f365_c3c6_499a_a60d_138e7e7023eb") public class Customer { @Id @Column(name = "CUSTOMER_ID") @GeneratedValue(strategy=GenerationType.IDENTITY) private Long customerId; @Column(name = "CUSTOMER_NAME") private String customer_name; @Column(name = "CUSTOMER_address_id") private int customer_address_id; @Column(name = "DAT_SRC_ID") private String dataSourceId; @OneToMany(fetch=FetchType.EAGER) @JoinColumn(name = "ORDER_CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID") private List<Order> order; }
控制器:
@RequestMapping(value="/getByCustid/{id}", method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE) public Customer getByCustid (@PathVariable Long id) { Customer s1 = customerRepository.findByCustomerId(id); return s1; }
仓库:
public interface CustomerRepository extends JpaRepository<Customer,Long> { public Customer findByCustomerId(Long customerId); }
以下是正在执行的查询:
select customer0_.CUSTOMER_ID as CUSTOMER1_0_, customer0_.CUSTOMER_address_id as CUSTOMER2_0_, customer0_.CUSTOMER_NAME as CUSTOMER3_0_, customer0_.DAT_SRC_ID as DAT_SRC_4_0_ from Customer customer0_ where customer0_.CUSTOMER_ID=? select order0_.ORDER_CUSTOMER_ID as ORDER_CU3_5_0_, order0_.ORDER_ID as ORDER_ID1_5_0_, order0_.ORDER_ID as ORDER_ID1_5_1_, order0_.ORDER_CUSTOMER_ID as ORDER_CU3_5_1_, order0_.DAT_SRC_ID as DAT_SRC_2_5_1_ from Ordertable order0_ where order0_.ORDER_CUSTOMER_ID=?
编辑:这与@Fetch(FetchMode.JOIN)有关- 链接:JPA渴望获取不加入
Hibernate:Hibernate对Fetch模式Eager进行的多个选择查询
为了检查FetchMode.JOIN是否正常工作,我在实体中添加了FetchMode.JOIN,如下所示,但Join Query仍然没有成功:
@Entity @Table(name="Customer", schema="cf_2583f365_c3c6_499a_a60d_138e7e7023eb") public class Customer { @OneToMany(fetch=FetchType.EAGER) @JoinColumn(name = "ORDER_CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID") @Fetch(FetchMode.JOIN) private List<Order> order; }
@Entity @Table(name="Ordertable", schema="cf_2583f365_c3c6_499a_a60d_138e7e7023eb") public class Order { @JsonIgnore @ManyToOne() @JoinColumn(name = "ORDER_CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID") @Fetch(FetchMode.JOIN) private Customer customer; }
在findByCustomerId基于该方法,而不是使用实际上会生成一个查询em.find。它将按照的方式创建一些东西SELECT c FROM Customer c WHERE c.customerId=:customerId。之后,它将注意到获取策略并获得所需的引用。这也在这里解释。该查询将完全按照您的指示执行操作。
findByCustomerId
em.find
SELECT c FROM Customer c WHERE c.customerId=:customerId
如果您要急于加载引用,则需要自己按照编写查询SELECT c FROM Customer c JOIN FETCH c.orders o WHERE c.customerId=:customerId,这将自动检索订单。
SELECT c FROM Customer c JOIN FETCH c.orders o WHERE c.customerId=:customerId
但是,customerId实际上是实体的主键或标识符,因此,您实际上应该使用findByIdor findOne方法(取决于Spring Data JPA版本)。这将使用,EntityManager.find后者应考虑映射信息并创建适当的查询。
customerId
findById
findOne
EntityManager.find