一)JPA接口的继承结构
1.1)SpringData 加入的主要是两个包
1.SpringData-Commons.jar
2.SpringData-jpa.jar
1.2)JPA接口分布在这两个包下每个接口主要的作用和方法介绍
1.JapResposttory:接口
该接口是开放是常用的接口,此接口为封装了对数据库常用的Curd操作。
此接口存放于SpringData-jpa.jar包内
主要的作用是:对父接口内的方法进行返回值类型的适配
源码方法
List<T> findAll();//查询全部
List<T> findAll(Sort var1);//排序查询(默认查询全部)
List<T> findAll(Iterable<ID> var1);
<S extends T> List<S> save(Iterable<S> var1);//保存 :此方法有两个作用 一是保存,二是更新,时机为数据中没数据为添加,数据库有数据,但是传入的对象和数据库中的数据不一致为修改
void flush();//刷新同步
<S extends T> S saveAndFlush(S var1);//保存并刷新同步
void deleteInBatch(Iterable<T> var1);//批量删除
void deleteAllInBatch();//删除全部
T getOne(ID var1);//查询一个
2.PagingAndSortingReosutory接口,此接口封装了分页查询和排序操作
源码
注意:
1)PagingAndSortingReosutory接口存在SpringData-Commons.jar包内
2)PagingAndSortingReosutory接口内的分页方法默认是查询全部进行分页
Iterable<T> findAll(Sort var1);//条件查询全部
Page<T> findAll(Pageable var1);//分页查询
3.CrudRespostory接口
CrudRespostory接口位于SpringData-Commons.jar包下,同PagingAndSortingReosutory接口为一个包,封装了常见的对数据库的CURD操作
源码列表
publicinterface CrudRepository<T, ID extendsSerializable> extends Repository<T, ID> {
<S extends T> S save(S entity);//保存
<S extends T> Iterable<S> save(Iterable<S> entities);//批量保存
T findOne(ID id);//根据id 查询一个对象。返回对象本身,当对象不存在时,返回null
Iterable<T> findAll();//查询所有的对象
Iterable<T> findAll(Iterable<ID> ids);//根据id列表查询所有的对象
boolean exists(ID id);//根据id 判断对象是否存在
long count();//计算对象的总个数
void delete(ID id);//根据id 删除
void delete(T entity);//删除一个对象
void delete(Iterable<? extendsT> entities);//批量删除,集合对象(后台执行时,一条一条删除)
void deleteAll();//删除所有(后台执行时,一条一条删除)
}
4.Repostory接口
位于SpringData-Commons.jar包下
空接口为标识接口
public interface Repository<T, ID extends Serializable> {
}
5)JpaSpecificationExecutor
该接口封装了比PagingAndSortingReosutory接口更加强大的查询方法,包括带条件的分页查询,条件查询等
该接口提供了JPA Criteria(动态查询)的支持
public interface JpaSpecificationExecutor<T> {
T findOne(Specification<T> var1); //返回一个
List<T> findAll(Specification<T> var1);//查询全部带条件
Page<T> findAll(Specification<T> var1, Pageable var2);//分页条件查询
List<T> findAll(Specification<T> var1, Sort var2);//排序条件查询
long count(Specification<T> var1);//计数
}
继承体系结构图
二)SpringData-JPA接口运行原理
使用 JPA接口进行持久化的操作的时候,并没对在接口内的书写任何的方法,接口是不能实例化的,那么SpingData是如何进行对数据库操作的呢?
1)dao接口
/**
* @project_name:hibernate02
* @date:2019/8/19:16:30
* @author:shinelon
* @Describe: 演示Spring Data JPA 进行持久层交互的时候,只需要继承指定的接口
* 接口接收两个的泛型,
* 第一个是操作的表的实体类
* 第二个是主键的生成策略为主键的类型
*/
public interface UserDao extends JpaRepository<Users, Integer> {
//没有任何抽象方法
}
2)测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext-hib.xml")
public class TestSpringDataJPA {
@Autowired
private UserDao userDao;
@Test
@Transactional
@Rollback(false)
public void testSpringDataJPASave(){
Users users = new Users();
users.setUsername("333");
users.setPassword("444");
this.userDao.save(users);
}
首先查看注入的dao对象是什么
@Test
public void test1(){
System.out.println(this.userDao);
}
}
注入的dao对象不是UserDao而是SimpleJpaRepository实现类
SimpleJpaRepository类其实就是Repostory接口体系的实现类
它实现了JpaRepository接口和JpaSpecificationExecutor接口,SpringData在进行数据库操作的时候实际上是将dao接口对象变成了SimpleJpaRepository对象
public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
private static final String ID_MUST_NOT_BE_NULL = "The given id must not be null!";
private final JpaEntityInformation<T, ?> entityInformation;
private final EntityManager em;
private final PersistenceProvider provider;
private CrudMethodMetadata metadata;
在看下UserDao的类型
类型是代理类对象,并且使用的还是java的动态代理类实现的
那么此时也就明了了,SpringData在进行持久化操作的时候,是通过动态代理将dao对象变成了SimpleJpaRepository对象
@Test
public void test1(){
//org.springframework.data.jpa.repository.support.SimpleJpaRepository@1dbaaf3
System.out.println(this.userDao);
System.out.println(this.userDao.getClass());
}
}
其实我们也可以自己通过SpringData提供的方法创建jpa的代理对象
要求
必须继承Repository接口
实例演示
需要JpaRepositoryFactory 就是用于创建Jpa代理对象的工厂,它接收一个EntityManager 对象,通过通过该对象构件,并且需要一个继承了Repository接口的接口
@PersistenceContext(name = "entityManagerFactory")
private EntityManager entityManager;
@Test
public void test1() {
//org.springframework.data.jpa.repository.support.SimpleJpaRepository@1dbaaf3
// System.out.println(this.userDao);
//System.out.println(this.userDao.getClass());
JpaRepositoryFactory factory = new JpaRepositoryFactory(entityManager);
UserDao repository = factory.getRepository(UserDao.class);
System.out.println(repository.getClass());
System.out.println(repository);
}
总结:
JPA实际根据Dao接口继承Repostory接口体系的接口,在进行配置的时候添加JPA扫描的dao包,在扫描的时候将继承了Repostory体系的接口通过动态代理创建Repostory体系的实现类SimpleJpaRepository的对象注入给Dao接口。