JPA、Hibernate、Spring Data JPA之间的关系

    技术2024-12-08  13

    Java 持久层框架访问数据库的方式大致分为两种。

     以SQL 核心,封装一定程度的 JDBC 操作,比如: MyBatis。以 Java 实体类为核心,将实体类的和数据库表之间建立映射关系,也就是我们说的ORM框架,如:Hibernate、Spring Data JPA

    JPA是啥?

    JPA全称为Java Persistence API(Java持久层API),它是Sun公司在JavaEE 5中提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具,来管理Java应用中的关系数据,JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。很多ORM框架都是实现了JPA的规范,如:Hibernate、EclipseLink。

    需要注意的是JPA统一了Java应用程序访问ORM框架的规范(JPA是一种规范)

     

    JPA为我们提供了以下规范:

    1. ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中

    2. JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发人员不用再写SQL了

    3. JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

     

    Hibernate是啥

    Hibernate是Java中的对象关系映射解决方案。对象关系映射或ORM框架是将应用程序数据模型对象映射到关系数据库表的技术。Hibernate 不仅关注于从 Java 类到数据库表的映射,也有 Java 数据类型到 SQL 数据类型的映射。

     

    Spring Data是啥

    Spring Data是Spring 社区的一个子项目,主要用于简化数据(关系型&非关系型)访问,其主要目标是使得数据库的访问变得方便快捷。

    它提供很多模板操作

    – Spring Data Elasticsearch

    – Spring Data MongoDB

    – Spring Data Redis

    – Spring Data Solr

    强大的 Repository 和定制的数据储存对象的抽象映射

    对数据访问对象的支持

     

    Spring Data JPA又是啥

    Spring Data JPA是在实现了JPA规范的基础上封装的一套 JPA 应用框架,虽然ORM框架都实现了JPA规范,但是在不同的ORM框架之间切换仍然需要编写不同的代码,而使用Spring Data JPA能够方便大家在不同的ORM框架之间进行切换而不需要更改代码。Spring Data JPA旨在通过将统一ORM框架的访问持久层的操作,来提高开发人的效率

     

     

    Spring Data JPA给我们提供的主要的类和接口

    Repository 接口:

    Repository

    CrudRepository

    JpaRepository

    Repository 实现类:

    SimpleJpaRepository

    QueryDslJpaRepository

     

    Spring Data JPA和Hibernate的关系

    Hibernate其实是JPA的一种实现,而Spring Data JPA是一个JPA数据访问抽象。也就是说Spring Data JPA不是一个实现或JPA提供的程序,它只是一个抽象层,主要用于减少为各种持久层存储实现数据访问层所需的样板代码量。但是它还是需要JPA提供实现程序,其实Spring Data JPA底层就是使用的 Hibernate实现。

    小结:

    Hibernate是JPA的一种实现,是一个框架

    JPA是一种规范(Java应用访问ORM的规范)

    Spring Data JPA是一种JPA的抽象层,底层依赖Hibernate

     

     

    spring-data-jpa能够帮助你完成业务逻辑代码的处理

    此时不需要UserDaoImpl这个类,只需要在UserRepository接口中定义一个方法

    User findByNameAndPassword(String name, String password);

    然后在service中调用这个方法即可,所有的逻辑只需要这么一行代码,一个没有实现的接口方法。通过debug信息,我们看到输出的sql语句是

    select * from user where name = ? and password = ?

    跟上面的传统方式一模一样的结果。原理是:spring-data-jpa会根据方法的名字来自动生成sql语句,我们只需要按照方法定义的规则即可,上面的方法findByNameAndPassword,spring-data-jpa规定,方法都以findBy开头,sql的where部分就是NameAndPassword,被spring-data-jpa翻译之后就编程了下面这种形态:

    where name = ? and password = ?

    在举个例,如果是其他的操作符呢,比如like,前端模糊查询很多都是以like的方式来查询。比如根据名字查询用户,sql就是

    select * from user where name like = ?

    这里spring-data-jpa规定,在属性后面接关键字,比如根据名字查询用户就成了

    User findByNameLike(String name);

    被翻译之后的sql就是

    select * from user where name like = ?

     

    定义规则:

     

     

    总结一下使用动态查询:原生api需要4步,而使用spring-data-jpa只需要一步,那就是重写匿名内部类的toPredicate方法

    eg:

    1 @Override 2 public Page<Student> search(final Student student, PageInfo page) { 4 return studentRepository.findAll(new Specification<Student>() { 5 @Override 6 public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 7 8 Predicate stuNameLike = null; 9 if(null != student && !StringUtils.isEmpty(student.getName())) { 10 stuNameLike = cb.like(root.<String> get("name"), "%" + student.getName() + "%"); 11 } 12 13 Predicate clazzNameLike = null; 14 if(null != student && null != student.getClazz() && !StringUtils.isEmpty(student.getClazz().getName())) { 15 clazzNameLike = cb.like(root.<String> get("clazz").<String> get("name"), "%" + student.getClazz().getName() + "%"); 16 } 17 18 if(null != stuNameLike) query.where(stuNameLike); 19 if(null != clazzNameLike) query.where(clazzNameLike); 20 return null; 21 } 22 }, new PageRequest(page.getPage() - 1, page.getLimit(), new Sort(Direction.DESC, page.getSortName()))); 23 }

     

    Processed: 0.046, SQL: 9