1.1 Spring Data Jpa底层原理解析
- 目标:知道它是怎么运行的?底层到底封装的是谁?、
- 明确一点:我们所使用的所有框架,底层大多数都使用了动态代理技术、反射技术来封装实现。
分析步骤:
- 我们只写了接口,但是没有写实现类,这个实现类就是Spring在运行的时候,注入的代理对象。
- Spring怎么知道生成的那个dao的实现类?因为在配置文件中指定了dao接口所在的包
- 生成的是什么对象?代理对象:通过jdk生成的动态代理对象
Proxy.newProxyInstance(类加载器,实现的接口列表,InvocationHandler)
JdkDynamicAopProxy: 这个是个对象,实现了InvocationHandler接口,所以这个类有invoke方法- 在JdkDynamicAopProxy的invoke方法中有个target对象,这个对象就是真正干活的对象
- 真正干活的对象:SimpleJpaRepository
- SimpleJpaRepository实现了我们dao接口继承的那两个接口,所以这个类中肯定有接口的所有方法
- 我们看到findOne方法中调用了em.find方法,这个em到底是谁?
1.2 Spring Data Jpa常用接口分析
2.1 查询方式一:接口定义方法查询:查询一个的两种方法
- 目标:查询一个对象的两种方法
- findOne(主键值):底层调用的是em.find() :立即加载
- getOne(主键值) : 底层调用的是em.getReference() : 延迟加载
package com.sunny.SpringDataJpaTest;
import com.sunny.dao.CustomerDao;
import com.sunny.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)//替换运行器
@ContextConfiguration("classpath:/applicationContext.xml")//指定核心配置文件
public class Interface_Method_Query {
@Autowired
private CustomerDao customerDao;
/**
* 查询一个对象
* findOne(); em.finc(Class,id) 立即加载
* getOne(); em.getReference(Class,id) 延迟加载
*
* 细节:
* 在使用延迟加载的时候,需要用到事务,如果没有事务,会报错
* could not initialize proxy - no Session 异常
*
* 为了解决这个异常:我们手动在测试方法中加入@Transactional注解
* 在以后真正的项目中,我们配置了声明式事务,这个注解就不用写了
*
*/
@Test
@Transactional
public void test01(){
//Customer c = customerDao.findOne(2L);
Customer c = customerDao.getOne(2L);
System.out.println(c);
}
}
2.2 查询方式一:接口定义方法查询:查询所有的分页与排序查询
目标:查询所有的分页与排序查询
import com.sunny.dao.CustomerDao;
import com.sunny.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)//替换运行器
@ContextConfiguration("classpath:/applicationContext.xml")//指定核心配置文件
public class Interface_Method_Query {
@Autowired
private CustomerDao customerDao;
/**
* 查询所有:
* 1)排序
* 2)分页
*/
@Test
public void test2(){
//排序对象
/**
* 第一个参数: 排序规则: asc | desc
* 第二个参数: 排序的实体类的属性名称
*/
Sort s = new Sort(Sort.Direction.DESC,"custId");
//分页
/**
* 第一个参数:当前页: 从0开始,0代表第一页;1代表第二页;2代表第三页........
* 第二个参数:页大小
* 第三个参数:排序对象,可以为空
*/
Pageable p = new PageRequest(0,2,s);
//查询
Page<Customer> page = c ustomerDao.findAll(p);
System.out.println("总记录数:"+page.getTotalElements());
System.out.println("总页数:"+page.getTotalPages());
Syst