七、Spring Data JPA对象导航查询

本文详细解析了一对多与多对一的查询方法,包括getOne和findOne在不同情况下的表现,以及如何通过修改实体类注解来控制加载策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、一对多查询

/**
 * 对象导航查询:测试一对多查询
 */
@Test
@Transactional // 解决在java代码中的no session问题
public void  testQuery1() {
    //查询id为1的客户
    Customer customer = customerDao.getOne(1l);
    System.out.println(customer);
    //对象导航查询,此客户下的所有联系人
    Set<LinkMan> linkMans = customer.getLinkMans();
    for (LinkMan linkMan : linkMans) {
        System.out.println(linkMan);
    }
}

findOne()结果相同
在这里插入图片描述
修改测试方法:
getOne()方法

@Test
@Transactional // 解决在java代码中的no session问题
public void  testQuery1() {
    //查询id为1的客户
    Customer customer = customerDao.getOne(1l);
    System.out.println(customer);
    //对象导航查询,此客户下的所有联系人
    /*Set<LinkMan> linkMans = customer.getLinkMans();
    for (LinkMan linkMan : linkMans) {
        System.out.println(linkMan);
    }*/
}

在这里插入图片描述
格式化sql语句

SELECT 
  customer0_.cust_id AS cust_id1_0_0_,
  customer0_.cust_address AS cust_add2_0_0_,
  customer0_.cust_industry AS cust_ind3_0_0_,
  customer0_.cust_level AS cust_lev4_0_0_,
  customer0_.cust_name AS cust_nam5_0_0_,
  customer0_.cust_phone AS cust_pho6_0_0_,
  customer0_.cust_source AS cust_sou7_0_0_ 
FROM
  cst_customer customer0_ 
WHERE customer0_.cust_id = ?

findOne()方法

@Test
@Transactional // 解决在java代码中的no session问题
public void  testQuery2() {
    // 查询id为1的客户
    Customer customer = customerDao.findOne(1l);
    // 对象导航查询,此客户下的所有联系人
    System.out.println(customer);
    /*Set<LinkMan> linkMans = customer.getLinkMans();
    for (LinkMan linkMan : linkMans) {
        System.out.println(linkMan);
    }*/
}

在这里插入图片描述
格式化sql语句:

SELECT 
  customer0_.cust_id AS cust_id1_0_0_,
  customer0_.cust_address AS cust_add2_0_0_,
  customer0_.cust_industry AS cust_ind3_0_0_,
  customer0_.cust_level AS cust_lev4_0_0_,
  customer0_.cust_name AS cust_nam5_0_0_,
  customer0_.cust_phone AS cust_pho6_0_0_,
  customer0_.cust_source AS cust_sou7_0_0_ 
FROM
  cst_customer customer0_ 
WHERE customer0_.cust_id = ?

可以从sql语句看出,一对多查询findOne()或者getOne()默认情况下都是延迟加载,查询客户时并没有查询客户对应的联系人信息

修改Customer类中的注解@OneToMany,添加fetch = FetchType.EAGER采用立即加载

@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<LinkMan> linkMans = new HashSet<LinkMan>();

再次执行getOne()findOne()方法,查看控制台打印的sql语句,可以看出在查询客户时,同时也查询了联系人

SELECT 
  customer0_.cust_id AS cust_id1_0_0_,
  customer0_.cust_address AS cust_add2_0_0_,
  customer0_.cust_industry AS cust_ind3_0_0_,
  customer0_.cust_level AS cust_lev4_0_0_,
  customer0_.cust_name AS cust_nam5_0_0_,
  customer0_.cust_phone AS cust_pho6_0_0_,
  customer0_.cust_source AS cust_sou7_0_0_,
  linkmans1_.lkm_cust_id AS lkm_cust9_1_1_,
  linkmans1_.lkm_id AS lkm_id1_1_1_,
  linkmans1_.lkm_id AS lkm_id1_1_2_,
  linkmans1_.lkm_cust_id AS lkm_cust9_1_2_,
  linkmans1_.lkm_email AS lkm_emai2_1_2_,
  linkmans1_.lkm_gender AS lkm_gend3_1_2_,
  linkmans1_.lkm_memo AS lkm_memo4_1_2_,
  linkmans1_.lkm_mobile AS lkm_mobi5_1_2_,
  linkmans1_.lkm_name AS lkm_name6_1_2_,
  linkmans1_.lkm_phone AS lkm_phon7_1_2_,
  linkmans1_.lkm_position AS lkm_posi8_1_2_ 
FROM
  cst_customer customer0_ 
  LEFT OUTER JOIN cst_linkman linkmans1_ 
    ON customer0_.cust_id = linkmans1_.lkm_cust_id 
WHERE customer0_.cust_id = ?

二、多对一查询

测试方法

@Test
@Transactional // 解决在java代码中的no session问题
public void  testQuery3() {
    LinkMan linkMan = linkManDao.findOne(1l);
    // 对象导航查询所属的客户
    //Customer customer = linkMan.getCustomer();
    //System.out.println(customer);
}

在默认情况下执行,格式化控制台sql语句如下

SELECT 
  linkman0_.lkm_id AS lkm_id1_1_0_,
  linkman0_.lkm_cust_id AS lkm_cust9_1_0_,
  linkman0_.lkm_email AS lkm_emai2_1_0_,
  linkman0_.lkm_gender AS lkm_gend3_1_0_,
  linkman0_.lkm_memo AS lkm_memo4_1_0_,
  linkman0_.lkm_mobile AS lkm_mobi5_1_0_,
  linkman0_.lkm_name AS lkm_name6_1_0_,
  linkman0_.lkm_phone AS lkm_phon7_1_0_,
  linkman0_.lkm_position AS lkm_posi8_1_0_,
  customer1_.cust_id AS cust_id1_0_1_,
  customer1_.cust_address AS cust_add2_0_1_,
  customer1_.cust_industry AS cust_ind3_0_1_,
  customer1_.cust_level AS cust_lev4_0_1_,
  customer1_.cust_name AS cust_nam5_0_1_,
  customer1_.cust_phone AS cust_pho6_0_1_,
  customer1_.cust_source AS cust_sou7_0_1_ 
FROM
  cst_linkman linkman0_ 
  LEFT OUTER JOIN cst_customer customer1_ 
    ON linkman0_.lkm_cust_id = customer1_.cust_id 
WHERE linkman0_.lkm_id = ?

可以看出,在默认情况下多对一查询时,使用个时立即加载,当查询联系人时,同时也查询了该联系人对应的客户信息

当然也可以在联系人实体类中修改为延迟加载:fetch = FetchType.LAZY

@ManyToOne(targetEntity = Customer.class, fetch = FetchType.LAZY)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Customer customer;

执行测试方法查看sql语句:

SELECT 
  linkman0_.lkm_id AS lkm_id1_1_0_,
  linkman0_.lkm_cust_id AS lkm_cust9_1_0_,
  linkman0_.lkm_email AS lkm_emai2_1_0_,
  linkman0_.lkm_gender AS lkm_gend3_1_0_,
  linkman0_.lkm_memo AS lkm_memo4_1_0_,
  linkman0_.lkm_mobile AS lkm_mobi5_1_0_,
  linkman0_.lkm_name AS lkm_name6_1_0_,
  linkman0_.lkm_phone AS lkm_phon7_1_0_,
  linkman0_.lkm_position AS lkm_posi8_1_0_ 
FROM
  cst_linkman linkman0_ 
WHERE linkman0_.lkm_id = ?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值