Spring Data JPA中的多表查询

对象导航查询

对象图导航查询是根据已经加载的对象,导航到他的关联对象。它利用类和类之间的关系来检索对象。例如:我们通过ID查询方式查出一个客户,可以调用Customer类中的getLinkMans()方法来获取该客户的所有联系人。

怎么用?[重点]

对象导航的使用要求是:两个对象之间必须存在关联关系

  • 查询一个客户,获取该客户下的所有联系人
// 两个查询语句:当需要用的时候查询
	@Autowired
	private CustomerDao customerDao;
	
	@Test
     // could not initialize proxy - no Session
	//由于是在java代码中测试,为了解决no session问题,将操作配置到同一个事务中
	@Transactional 
	public void testFind() {
		Customer customer = customerDao.findOne(5l);
		Set<LinkMan> linkMans = customer.getLinkMans();//对象导航查询
		for(LinkMan linkMan : linkMans) {
  			System.out.println(linkMan);
		}
	}

少表导航到多表:默认延迟加载

  • 查询一个联系人,获取该联系人的所有客户
// 立即加载:左外连接
	@Autowired
	private LinkManDao linkManDao;
	
	
	@Test
	public void testFind() {
		LinkMan linkMan = linkManDao.findOne(4l);
		Customer customer = linkMan.getCustomer(); //对象导航查询
		System.out.println(customer);
	}

多表导航到少表:默认立即加载

对象导航查询的问题分析[了解就好]

  • 问题1:我们查询客户时,要不要把联系人查询出来?
  • 分析:如果我们不查的话,在用的时候还要自己写代码,调用方法去查询。如果我们查出来的,不使用时又会白白的浪费了服务器内存。
  • 解决:采用延迟加载的思想。通过配置的方式来设定当我们在需要使用时,发起真正的查询。

配置方式:

	/**
	 * 在客户对象的@OneToMany注解中添加fetch属性
	 * 		FetchType.EAGER	:立即加载
	 * 		FetchType.LAZY	:延迟加载
	 */
	@OneToMany(mappedBy="customer",fetch=FetchType.EAGER)
	private Set<LinkMan> linkMans = new HashSet<>(0);
  • 问题2:我们查询联系人时,要不要把客户查询出来?
  • 分析:例如:查询联系人详情时,肯定会看看该联系人的所属客户。如果我们不查的话,在用的时候还要自己写代码,调用方法去查询。如果我们查出来的话,一个对象不会消耗太多的内存。而且多数情况下我们都是要使用的。
  • 解决: 采用立即加载的思想。通过配置的方式来设定,只要查询从表实体,就把主表实体对象同时查出来

配置方式:

	/**
	 * 在联系人对象的@ManyToOne注解中添加fetch属性
	 * 		FetchType.EAGER	:立即加载
	 * 		FetchType.LAZY	:延迟加载
	 */
	@ManyToOne(targetEntity=Customer.class,fetch=FetchType.EAGER)
	@JoinColumn(name="cst_lkm_id",referencedColumnName="cust_id")
	private Customer customer;

使用Specification查询

    /**
     * Specification的多表查询
     */
    @Test
    public void testFin1d() {
        Specification<LinkMan> spec = new Specification<LinkMan>() {
            public Predicate toPredicate(Root<LinkMan> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //Join代表链接查询,通过root对象获取
                //创建的过程中,第一个参数为关联对象的属性名称,第二个参数为连接查询的方式(left,inner,right)
                //JoinType.LEFT : 左外连接,JoinType.INNER:内连接,JoinType.RIGHT:右外连接
                Join<LinkMan, Customer> join = root.join("customer",JoinType.INNER);
                return cb.like(join.get("custName").as(String.class),"TBD云集中心11111");
            }
        };
        List<LinkMan> list = linkManDao.findAll(spec);
        for (LinkMan linkMan : list) {
            System.out.println(linkMan);
        }
    }
发布了254 篇原创文章 · 获赞 70 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/zhizhengguan/article/details/104050588