渴望获取在休眠模式下执行左联接,但在springboot / JPA中触发单独的SQL查询

时间:2019-05-22 03:23:23

标签: java spring hibernate spring-boot eager-loading

我看到很多帖子,其中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=?

EDIT:这与@Fetch(FetchMode.JOIN)有关吗-链接:JPA eager fetch does not join

Hibernate: Multiple select queries made by Hibernate for Fetch mode 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;
}

1 个答案:

答案 0 :(得分:0)

findByCustomerId实际上将基于该方法而不是使用em.find来生成查询。它将按照SELECT c FROM Customer c WHERE c.customerId=:customerId的方式创建内容。之后,它将注意到获取策略并获得所需的引用。 here也对此进行了说明。该查询将完全按照您的指示执行操作。

如果您想急切地加载引用,则需要按照SELECT c FROM Customer c JOIN FETCH c.orders o WHERE c.customerId=:customerId自己编写查询,这将自动检索订单。

但是customerId实际上是您实体的主键或标识符,因此,您实际上应该使用findByIdfindOne方法(取决于您的Spring Data JPA版本)。这将使用EntityManager.find,它应考虑映射信息并创建适当的查询。